Summary in
README.mdunder "WASM Event Flow". This file has additional details.
webtyp/form uses a reactive binding model via webtyp.com/dom signals. Unlike traditional imperative mounting where a form must "attach" listeners after being added to the DOM, this form is reactive by construction.
Each field is bound to a SignalString for its value and another for its error state.
// Simplified field binding in Render()
in := dom.NewElement("input").
Bind(field.value).
On("input", func(e dom.Event) {
field.value.Set(e.TargetValue())
if err := field.input.Validate(field.value.Get()); err != nil {
field.err.Set(err.Error())
} else {
field.err.Set("")
}
})
errSpan := dom.NewElement("span").
BindText(field.err)- IME & Cursor Safety: Two-way
Bindinwebtyp/domis designed to be cursor-safe. It detects if the element is currently focused and active (e.g., during IME composition for accents or CJK characters) and avoids patching thevalueattribute if it matches the current signal value. This prevents cursor jumps and broken compositions. - Surgical Updates: When a user types, only the specific error text node and CSS classes are patched in the DOM. The
<input>node itself is never replaced or re-rendered. - No Lifecycle Hooks: There is no
OnMountorOnUnmount. The form is adom.Componentthat provides aRender() *dom.Elementmethod. The DOM tree it returns is already "alive" with signal bindings.
Live Validation:
Triggered on the input event. It updates the field's value signal and performs validation, updating the error signal immediately.
Submission:
Triggered on the form's submit event.
e.PreventDefault()f.SyncValues(f.data)— pulls current values from signals into the struct.f.Validate()— full validation check.f.submitting.Set(true)— toggles the submit button's loading state.f.onSubmit(f.data, done)— user callback.done(err)— called by user to signal completion.f.submitting.Set(false)and optionalf.reset().