useForm
function useForm<ErrorFields extends Object>(options?: { errorClass?: string }): FormApi;Creates an isolated form context: one error store, one field registry, one pair of submission signals. Call it once per form.
The ErrorFields type parameter names the keys of the errors store. It is optional, and without it errors is loosely typed.
type Fields = { email: string; password: string };const { errors } = useForm<Fields>();options.errorClass
A class name toggled on any element that fails validation, alongside aria-invalid="true". Removed on the next input into that field. Omit it to style against aria-invalid only.
validate
validate(ref: HTMLElement, accessor?: () => Validator[] | Falsy): voidRegisters an element, used as a directive.
<input name='email' required use:validate /><input name='handle' use:validate={[minLength(3)]} />Registration is deferred to a microtask, so a field is not queryable in the same synchronous tick it renders in. Attaches blur and input handlers by assigning onblur and oninput, which replaces any handler already assigned that way on the same element.
The store key comes from name, falling back to data-name.
formSubmit
formSubmit(ref: HTMLFormElement, accessor: () => OnFormSubmit): voidTakes over a form’s submit event, used as a directive.
<form use:formSubmit={onSubmit}>On attach it sets novalidate on the form. On submit it calls preventDefault() and runs the same sequence as submit, passing the form element to your callback. On reset it clears every error.
submit
submit<Payload>( callback: (payload: Payload) => MaybePromise<void | Partial<ErrorFields>>, payload?: Payload,): Promise<void>Runs validation and, if everything passes, the callback. Use it when there is no form element.
- Every registered field is checked in registration order.
- The first failing field still in the document is focused and scrolled into view, and the submission stops.
- Failing fields that have been removed from the document are dropped from the registry rather than blocking.
isSubmittingbecomestrue, the callback runs,isSubmittingbecomesfalse.- A returned object is merged into
errors. Anything else clears all errors and setsisSubmitted.
An exception thrown by the callback propagates and leaves isSubmitting at true. Catch inside the callback.
errors
errors: Partial<ErrorFields>A Solid store proxy of current messages, keyed by field name. Reading errors.email in JSX subscribes to that key alone. Keys that match no registered field are allowed and are how form-level messages are rendered.
isSubmitting
isSubmitting: () => booleantrue from the moment validation passes until the callback settles. Field checks that fail before the callback runs never flip it, so it does not flash on a failed submit.
isSubmitted
isSubmitted: () => booleantrue after a submission whose callback returned no errors. Reset to false by any input into a registered field, by the next submit, and when formSubmit attaches.
validateRef
validateRef(...validators: Validator[]): (ref: HTMLElement) => voidReturns a ref-compatible function that registers an element. The value form of use:validate, for fields inside child components. Validators are passed as arguments rather than as an array.
<input name='email' required ref={validateRef(isCorporateAddress)} />See Child components.
validateField
validateField(fieldName: keyof ErrorFields): Promise<boolean>Checks one field and resolves to whether it passed. Focuses and scrolls to the element on failure. Returns false for a field that was never registered, so a typo in the name reads as invalid rather than throwing.
Useful for multi-step forms, where a step is gated on a subset of fields:
if (!(await validateField('email'))) return;goToStep(2);getFieldValue
getFieldValue(fieldName: keyof ErrorFields): string | undefinedReads the current value of a registered field’s element. Returns undefined for an unregistered field, and for elements with no value property such as a div.
This is a direct DOM read, not a reactive source. It does not track in an effect or memo. For cross-field rules, read the other element inside a validator instead:
const mustMatch: Validator<HTMLInputElement> = el => el.value !== getFieldValue('password') && 'Passwords do not match';