Forms
Forms use ordinary HTML elements. A small field component can own its label and layout while forwarding input-specific attributes from each call site.
A reusable form field
Place { attrs... } on the inner <input> so undeclared caller attributes such as type, name, and required reach that element.
package views
import "github.com/gsxhq/gsx"
component Field(label string, attrs gsx.Attrs) {
<div class="field"><label>{ label }</label><input class="control" { attrs... }/></div>
}
component LoginForm() {
<form method="post" action="/login">
<Field label="Email" type="email" name="email" required/>
<Field label="Password" type="password" name="password" required/>
<button type="submit">Sign in</button>
</form>
}Renders:
<form method="post" action="/login"><div class="field"><label>Email</label><input class="control" type="email" name="email" required></div><div class="field"><label>Password</label><input class="control" type="password" name="password" required></div><button type="submit">Sign in</button></form>label binds to the component param; the remaining attributes form the bag that Field forwards. Its own class="control" stays in place, and a caller-supplied class would merge at the spread position. See Attributes for spread ordering and Styling for class merging.
Server-side validation is ordinary Go
Parse and validate the request in the HTTP handler, then pass submitted values and field errors back to the form component as typed params. With net/http, use Request.ParseForm; with a web framework, use its normal binding and validation support. gsx only renders the resulting form state.