useNotForm
Creates and returns a fully typed, reactive form instance.
Signature
function useNotForm<TSchema extends ObjectSchema>(
config: UseNotFormConfig<TSchema>
): NotFormInstance<TSchema>
Config
schema
MaybeRefOrGetter<TSchema> required
Standard Schema compliant validation schema. Accepts a plain value, a
ref, or a computed — it is resolved on every validation run, so a reactive schema works correctly.initialValues
DeepPartial<InferInput<TSchema>>
Starting values for the form. Deeply cloned on init — mutating the original after calling
useNotForm has no effect.initialErrors
StandardSchemaV1.Issue[]
Errors to populate on creation. Useful when rendering server-side validation results on the initial load.
validateOn
Partial<Record<ValidationTrigger, boolean>>
Which DOM events trigger field validation. Defaults:
onBlur: true, onChange: true, onInput: true, everything else false.validationMode
Partial<Record<'eager' | 'lazy', boolean>>
eager (default) — re-validates on input/change while an error exists. lazy — validates only on blur or submit.onSubmit
(values: InferOutput<TSchema>) => void | Promise<void>
Called after successful validation when the form is submitted. Receives the schema's validated output. Never called when validation fails.
Return value
Values
values
InferInput<TSchema>
Deeply reactive form values. Access directly with
form.values.email — no .value needed. Use with v-model for two-way binding.setValue(path, value)
method
Sets a value by dot-separated path without triggering validation. Use this for programmatic updates or custom inputs.
Touch
touchedFields
Set<Paths<TInput>>
The set of field paths the user has interacted with. All paths are populated when the form is submitted.
isTouched
ComputedRef<boolean>
true when at least one field has been touched.touchField(path)
method
Marks a field as touched. Called automatically by
onBlur.Dirty
dirtyFields
Set<Paths<TInput>>
The set of field paths whose current value differs from the initial value.
isDirty
ComputedRef<boolean>
true when at least one field is dirty.dirtyField(path)
method
Marks a field as dirty. Called automatically when a value changes.
Errors
errors
StandardSchemaV1.Issue[]
The raw issues from the last validation run. Reactive array — use the provided methods to mutate it.
errorsMap
ComputedRef<Partial<Record<Paths, string>>>
Flat map of field path to its first error message. Use for direct template access without calling
getFieldErrors.setError(issue)
method
Replaces the existing error for the same path, or appends it if none exists.
setErrors(issues)
method
Replaces all current errors at once.
clearErrors()
method
Removes all active errors.
getFieldErrors(path)
method
Returns all issues for a specific field path.
Validation
isValidating
Ref<boolean>
true while any validation run is in progress.validate()
() => Promise<StandardSchemaV1.Result>
Runs the full schema. Replaces all errors with the result. Returns the schema result — check
result.issues to determine pass/fail.validateField(path)
(path) => Promise<StandardSchemaV1.Result>
Runs the full schema but only updates errors for the given field. All other field errors are left untouched.
isValid
ComputedRef<boolean>
true when there are no active errors.Submission
submit(event)
(event: Event) => Promise<void>
Marks all fields as touched and dirty, validates the form, then calls
onSubmit if validation passes. Calls event.preventDefault() when validation fails or when onSubmit is defined. Bind to @submit on the form element.isSubmitting
Ref<boolean>
true while onSubmit is running.Reset
reset(values?, errors?)
method
Restores the form to its initial state. Clears all errors, touched fields, and dirty fields. If
values or errors are passed, they replace the stored baseline — the next call to reset() with no arguments returns to these new values.Examples
Reactive schema
const requireAddress = ref(false)
const schema = computed(() =>
z.object({
name: z.string().min(2),
address: requireAddress.value
? z.string().min(1)
: z.string().optional(),
})
)
const form = useNotForm({ schema, initialValues: { name: '', address: '' } })
Server-side errors after submit
const form = useNotForm({
schema,
onSubmit: async (values) => {
try {
await $fetch('/api/signup', { method: 'POST', body: values })
} catch {
form.setError({
path: [{ key: 'email' }],
message: 'This email is already registered',
})
}
},
})
Programmatic validation
// Full form
const result = await form.validate()
if (result.issues) {
console.log('Failed:', result.issues)
} else {
console.log('Output:', result.value) // Typed schema output
}
// Single field
await form.validateField('email')