use-form
Fully typed form state with validation, field arrays, and submission.
| Package | @vizejs/composable/use-form |
| Own the source | vize lib pull composable:use-form |
| Runtime exports | useForm |
| Gzip budget | 7168 B |
Usage
import { useForm } from "@vizejs/composable/use-form";
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useForm |
state | experimental | safe | stable | reactive-scope | web, server, worker, native, desktop, terminal | AbortController, DOMException, structuredClone |
tryOnScopeDispose, validateStandardSchema |
API
useForm
Fully typed form state with validation, field arrays, and submission. The value type is inferred from initialValues; every path is a template-literal key, so field("address.city") returns controls whose value is typed as the city's type and misspelled paths do not compile. Validation combines a Standard Schema v1 validator (Zod, Valibot, ArkType, … via the ~standard protocol), a whole-form validator, and per-field validators; all may be asynchronous. A newer validation aborts older ones through their signal and their results are discarded, so a slow check can never overwrite fresher errors. This composable owns the values. @vizejs/ui/form owns accessible error presentation (error summaries, focus management, native constraint validation); feed FormControls.errors into it to render them. Server rendering: pure state, no host access; validation never runs automatically during setup, so server and client render the same markup. Pending validations are aborted when the owning scope stops.
function useForm<Values extends object, Output = Values>( options: UseFormOptions<Values, Output>, ): FormControls<Values, Output>
const form = useForm({
initialValues: { name: "", address: { city: "" }, tags: [] as string[] },
validators: { name: (name) => (name ? undefined : "Required") },
onSubmit: (values) => api.save(values),
});
const city = form.field("address.city"); // city.value: Ref<string>
const tags = form.fieldArray("tags");
tags.append("vue");
Types
FieldValidatorContext
Context passed to field validators.
| Member | Type | Description |
|---|---|---|
values |
Values |
Current form values (undefined for standalone fields). |
path |
string |
Dotted path of the validated field. |
signal |
AbortSignal |
Aborted when a newer validation supersedes this one. |
UseFormOptions
Options for useForm.
| Member | Type | Description |
|---|---|---|
initialValues |
Values | (() => Values) |
Initial values, or a factory producing fresh initial values. |
schema? |
StandardSchemaV1<NoInfer<Values>, Output> |
Standard Schema v1 validator for the whole form. Its output becomes the submitted value. |
validate? |
NoInfer<FormValidator<Values>> |
Plain whole-form validator. |
validators? |
NoInfer<FormFieldValidators<Values>> |
Plain per-field validators keyed by path. |
validateOn? |
FormValidationTrigger |
When fields validate before the first submit. |
revalidateOn? |
FormValidationTrigger |
When fields re-validate after the first submit. |
onSubmit? |
(value: Output, context: { readonly signal: AbortSignal }) => unknown |
Default submit handler for FormControls.submit. |
SetFieldValueOptions
Options for FormControls.setValue.
| Member | Type | Description |
|---|---|---|
touch? |
boolean |
Mark the field touched. |
validate? |
boolean |
Validate the field after setting it. |
FormFieldControls
Reactive controls for one field, returned by FormControls.field.
| Member | Type | Description |
|---|---|---|
path |
Path |
Dotted path of the field (also a suitable name attribute). |
value |
WritableComputedRef<Value> |
Writable value bound to the form state (use with v-model). |
errors |
ComputedRef<readonly string[]> |
Current error messages. |
error |
ComputedRef<string | undefined> |
First error message. |
dirty |
ComputedRef<boolean> |
Whether the value differs from its initial value. |
touched |
ComputedRef<boolean> |
Whether the field was blurred or touched programmatically. |
validating |
ComputedRef<boolean> |
Whether a validation of this field is pending. |
onBlur |
() => void |
Mark the field touched (wire to blur); validates when configured. |
validate |
() => Promise<boolean> |
Validate this field. |
reset |
() => void |
Restore the initial value and clear errors and touched state. |
FormArrayEntry
One entry of a field array, with a stable key for v-for.
| Member | Type | Description |
|---|---|---|
key |
number |
Stable key that follows the item through moves. |
index |
number |
Current index. |
path |
|
Dotted path of the item, e.g. items.2. |
value |
Item |
Current item value. |
FormFieldArrayControls
Typed operations on an array field, returned by FormControls.fieldArray.
| Member | Type | Description |
|---|---|---|
entries |
ComputedRef<readonly FormArrayEntry<Item, Path>[]> |
Entries with stable keys. |
append |
(...items: Item[]) => void |
Append items. |
prepend |
(...items: Item[]) => void |
Prepend items. |
insert |
(index: number, item: Item) => void |
Insert an item at index. |
remove |
(index: number) => void |
Remove the item at index, shifting errors and touched state. |
move |
(from: number, to: number) => void |
Move an item from one index to another, carrying its state along. |
swap |
(first: number, second: number) => void |
Swap two items. |
replace |
(items: readonly Item[]) => void |
Replace all items and reset their state. |
FormControls
Reactive state and actions returned by useForm.
| Member | Type | Description |
|---|---|---|
values |
Ref<Values> |
Current values. Mutations are tracked (dirty state derives from them). |
errors |
Readonly<ShallowRef<FormErrorRecord>> |
Current errors keyed by path; "" holds form-level errors. |
valid |
ComputedRef<boolean> |
Whether no errors are currently recorded. |
dirty |
ComputedRef<boolean> |
Whether any value differs from its initial value. |
validating |
ComputedRef<boolean> |
Whether any validation is pending. |
submitting |
Readonly<Ref<boolean>> |
Whether a submission is in progress. |
submitCount |
Readonly<Ref<number>> |
Number of submit attempts. |
field |
<Path extends FormPath<Values>>( path: Path, ) => FormFieldControls<FormPathValue<Values, Path>, Path> |
Typed controls for one field. |
fieldArray |
<Path extends FormArrayPath<Values>>( path: Path, ) => FormFieldArrayControls<FormArrayItem<Values, Path>, Path> |
Typed operations for an array field. |
getValue |
<Path extends FormPath<Values>>(path: Path) => FormPathValue<Values, Path> |
Read the value at a path. |
setValue |
<Path extends FormPath<Values>>( path: Path, value: FormPathValue<Values, Path>, options?: SetFieldValueOptions, ) => void |
Write the value at a path. |
setValues |
(values: Partial<Values>, options?: { readonly merge?: boolean }) => void |
Replace (or shallowly merge) the values without touching initial values. |
isTouched |
(path: FormPath<Values>) => boolean |
Whether a field was touched. |
setErrors |
(errors: FormErrors<Values>) => void |
Replace errors (for example with server-side errors). |
clearErrors |
(path?: FormPath<Values> | "") => void |
Clear errors of one path, or all errors. |
validate |
() => Promise<FormResult<Output>> |
Run every validator, aborting any older validation still in flight. |
submit |
( handler?: (value: Output, context: { readonly signal: AbortSignal }) => unknown, ) => Promise<FormResult<Output>> |
Validate and, when valid, call handler (or the onSubmit option). A newer submit aborts an older one's pending validation. |
handleSubmit |
( handler?: (value: Output, context: { readonly signal: AbortSignal }) => unknown, ) => (event?: Event) => Promise<FormResult<Output>> |
Create a submit event listener that prevents the native submission. |
reset |
(values?: Values) => void |
Restore initial values (or install new ones) and clear all state. |