Server Integration & Persistence
Server-side validation errors
Map a backend's validation error response onto form.errors — no hand-rolled unwrapping in every project.
import { applyServerErrors } from '@macrulez/vue-form-schema'
const res = await fetch('/api/users', { method: 'POST', body: JSON.stringify(form.values.value) })
if (!res.ok) {
const { formErrors } = applyServerErrors(form, await res.json(), { format: 'laravel' })
if (formErrors.length) toast.error(formErrors[0]) // errors not tied to a specific field
}Built-in formats:
'laravel'
{ message, errors: { field: ["msg", ...], "nested.field": [...] } }
'drf'
{ field: ["msg"], nested: { field: ["msg"] } } (flattened to dot-paths); non_field_errors / detail become formErrors.
'flat'
{ field: "msg" | ["msg", ...] } — the default; matches most hand-rolled APIs.
Or pass your own mapper for anything else: (raw) => ({ fieldErrors: {...}, formErrors: [...] }).
Field errors set this way behave like any other entry in errors — the next time that field validates client-side (on blur by default, or on every keystroke with validateOn: 'input'), it's recomputed from the schema's own validators and the server error is naturally replaced. submit() also fully recomputes errors, so a stale server error never survives into the next submit attempt.
applyServerErrors(form, raw, options?):
format
'laravel' | 'drf' | 'flat' | ((raw) => ...) · default: 'flat'
Built-in format name or a custom mapper.
touch
boolean · default: true
Mark affected fields as touched so errors show immediately.
merge
boolean · default: true
Merge into existing errors instead of replacing them.
normalizeServerErrors(raw, format?) runs the same mapping without touching a form, if you just want { fieldErrors, formErrors } yourself.
Persisted forms
useForm({
schema,
persist: 'local', // or 'session'
persistKey: 'checkout', // optional — defaults to a hash of field names
})Values are restored from storage on onMounted. reset() clears the stored value. SSR-safe: the storage read is guarded by typeof window !== 'undefined'.