Skip to content

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.

gsx
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:

html
<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>

▶ Open in Playground

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.