Submission Handling
function LoginForm() {
const form = useForm({
initialValue: { email: "", password: "" },
onSubmit: async (form) => {
await login(form.value);
},
onSubmitError: (form, error) => {
toast.error("Failed to log in");
},
});
return <form onSubmit={form.handleSubmit}>{/* ... */}</form>;
}handleSubmit:
- Waits out any pending validation.
- If the form is invalid, marks it
touched(so errors on never-blurred fields become visible) and callsonSubmitInvalid, then returns. - Otherwise sets
submittingtotrue, callsonSubmit, and falls back toonSubmitErrorif it throws/rejects.
A no-op on a re-entrant call while already submitting. The event parameter
is optional and used only for preventDefault(), so the same call works from a
React Native onPress, any caller with no event, or a web <form onSubmit> as
shown above.
Disabling the submit button while submitting
submitting (and dirty, for a "nothing to save" state) are ordinary reactive
state, so gate the button like any other field property:
<Watch api={form} select={(f) => [f.submitting, f.dirty] as const}>
{(form, [submitting, dirty]) => (
<button type="submit" disabled={submitting || !dirty}>
Save
</button>
)}
</Watch>;Disabling the whole form while submitting
Set form.disabled = true around onSubmit's work.
disabled
cascades from a field down through every already-registered descendant, so
form.disabled = true reaches every field in the tree without watching
submitting anywhere:
const form = useForm({
initialValue: { email: "", password: "" },
onSubmit: async (form) => {
form.disabled = true;
try {
await login(form.value);
} finally {
form.disabled = false;
}
},
});disabled on its own only skips validation; it doesn't reach the DOM by itself.
For it to actually disable an input, the component rendering that input has to
read its own field's disabled and fold it into whatever disabled prop the
caller passed in, the same way TextField does (see
Basic):
const isDisabled = disabled || field.disabled;Each TextField is already subscribed to just its own field via useWatch, so
disabling a 50-field form during submit re-renders only the fields whose
disabled actually flipped, not LoginForm itself.
What's next
FormApi— full reference on JSR