Errors
Errors are checked on every change but shown when it's time — so the user isn't scolded while still typing.
When errors are shown
mode | A field error is visible |
|---|---|
'blur' (default) | After the user leaves the field (touch) |
'input' | As soon as the value changes, or after leaving the field |
'submit' | Only after a submit attempt |
After the first submit attempt (handleSubmit or validate) all errors are visible regardless of the mode. All current errors, including hidden ones, are in form.allErrors.
const form = useForm(Signup, { initial, mode: 'input' });Server errors
If the submit handler throws an error with a Laravel 422 response (axios, ofetch), the errors are spread over the fields automatically — nothing to do. A field error disappears as soon as the user changes that field; editing other fields keeps it.
For another response format use the extractErrors option of useForm or call setErrors manually:
// axios / ofetch: 422 is handled automatically
const submit = form.handleSubmit((data) => axios.post('/api/signup', data));
// fetch: no exception on 422 — call setErrors yourself
const submitFetch = form.handleSubmit(async (data) => {
const res = await fetch('/api/signup', { method: 'POST', body: JSON.stringify(data) });
if (res.status === 422) {
const { errors } = await res.json(); // { email: ['The email has already been taken.'] }
form.setErrors(errors);
return;
}
form.reset();
});Language and field names
Set for the form with the same options as in validate. For fully custom texts see custom lang file.
import ru from 'tinyval/locales/ru';
const form = useForm(Signup, {
initial: { name: '', email: '' },
messages: { ...ru, required: 'Поле «{label}» обязательно' },
labels: { name: 'Имя', email: 'Почта' },
});Focus the first error
On a failed submit the focus moves to the first field with an error in markup order — fields are found by the name attribute, so they need name with the path (name="email", name="items.0.title"). useField sets it for you. Disable with focusOnError: false.
For custom logic there is onInvalid — it receives the visible errors:
const submit = form.handleSubmit(save, (errors) => {
toast.error(`Please fix ${Object.keys(errors).length} fields`);
});