GitHub

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')