Forms · validation
Forms with rules — required, email, lengths, patterns, matching fields and async checks — errors that appear at the right moment, server errors on the right field, focus and a shake on what needs fixing.
○ untouched
not sent
try “ada” as a username · an email ending in @test.com fails on the server
Usage
import { createForm, rules, Form, FormField } from "./components/form.js";import { Input, Textarea } from "./components/input.js";const { required, email, minLength, matches, pattern } = rules; const form = createForm({ initial: { name: "", email: "", username: "", password: "", confirm: "", agree: false }, rules: { email: [required(), email()], username: [required(), async (v) => (await api.taken(v)) ? "Taken" : null], // a spinner while it asks password: [required(), minLength(8), pattern(/\d/, "Include a digit")], confirm: [required(), matches("password", "Passwords don't match")], agree: [required("You need to accept the terms")], }, // throw { fields: { email: "…" } } and the server's errors land on the fields onSubmit: async (values) => { await api.signUp(values); },}); Form({ form, children: html` ${Input({ label: "Email", ...form.field("email") })} // value, error, onBlur, required, loading ${FormField({ label: "Country", error: form.field("country").error, children: Select({ … }) })} ${Button({ type: "submit", label: "Create account", loading: form.submitting })}` })// errors show once a field is left or the form is sent; then they follow the typing.// Sending: every field is checked, the first wrong one gets the focus, the wrong ones shake.// form.valid() · form.dirty() · form.reset() · form.setErrors({ … }) · form.get()