Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

createForm

Coordinates validation across multiple inputs. Provides submit(), reset(), and aggregate validity state.


AdvancedApr 5, 2026

Usage

Creating a Form

Create a form and register validation contexts. Each validation owns its rules for a single input:

ts
import { createForm, createValidation } from '@vuetify/v0'
import { shallowRef } from 'vue'

const form = createForm()
const email = shallowRef('')
const validation = createValidation({
  value: email,
  rules: ['required', 'email'],
})

form.register({ value: validation })

await form.submit()

console.log(validation.errors.value) // ['Required']

form.reset()

Auto-Registration

When a createValidation instance is created inside a component that has a parent form context, it auto-registers with the form — no manual form.register() needed:

vue
<script setup lang="ts">
  import { createValidation } from '@vuetify/v0'
  import { shallowRef } from 'vue'

  // Parent provides form context — this validation auto-registers
  const email = shallowRef('')
  const validation = createValidation({
    value: email,
    rules: ['required', 'email'],
  })
</script>

Disabled and Readonly

The form exposes disabled and readonly as reactive refs. Components can read these to conditionally disable inputs:

ts
const form = createForm({ disabled: true })

form.disabled.value = false // Toggle at runtime

Injecting a Form Context

Use useForm to inject an existing form context provided by a parent component:

ts
import { useForm } from '@vuetify/v0'

const form = useForm() // Returns undefined if no parent form

Context / DI

Use createFormContext to share a form instance across a component tree:

ts
import { createFormContext } from '@vuetify/v0'

export const [useContactForm, provideContactForm, contactForm] =
  createFormContext({ namespace: 'app:contact-form' })

// In parent component (e.g., ContactForm.vue)
provideContactForm()

// In any child component (e.g., submit button, field)
const form = useContactForm()
await form.submit()

Validations inside the component tree auto-register with the provided form — no manual form.register() needed.

Options

OptionTypeDefaultNotes
disabledMaybeRefOrGetter<boolean>falseWhen truthy, child components should disable interaction. Read via form.disabled
readonlyMaybeRefOrGetter<boolean>falseWhen truthy, child components should prevent editing. Read via form.readonly

Architecture

createForm is a pure registry. Validations register with it for coordination:

Form Architecture

Use controls to zoom and pan. Click outside or press Escape to close.

Form Architecture

Reactivity

Form-level state is fully reactive.

Property/MethodReactiveNotes
isValidComputed from all registered validations
isValidatingComputed from all registered validations
disabledShallowRef, read by components
readonlyShallowRef, read by components

Examples

Contact Form

A contact form with field validation using createValidation, demonstrating submit(), reset(), and aggregate isValid/isValidating state.

3 fields registered · validation: not run

API Reference

The following API details are for the createForm composable.

Functions

createForm

(options?: FormOptions) => FormContext<FormTicketInput, FormTicket<FormTicketInput>>

Creates a new form instance. A form is a pure registry of validation contexts. Validations register themselves via `useForm()` injection. The form coordinates submit, reset, and aggregate state across all registered validations.

createFormContext

(_options?: FormContextOptions) => ContextTrinity<FormContext<FormTicketInput, FormTicket<FormTicketInput>>>

Creates a new form context using the Trinity pattern.

useForm

(namespace?: string) => R | undefined

Returns the current form instance.

Options

events

boolean | undefined

Enable event emission for registry operations

Default: false

reactive

boolean | undefined

Enable reactive behavior for registry operations

Default: false

disabled

MaybeRefOrGetter<boolean> | undefined

Whether the form starts disabled.

readonly

MaybeRefOrGetter<boolean> | undefined

Whether the form starts readonly.

Properties

collection

ReadonlyMap<ID, E>

The collection of tickets in the registry

size

number

The number of tickets in the registry

disabled

MaybeRefOrGetter<boolean>

Whether the form is disabled. Components can read this to conditionally disable inputs.

readonly

MaybeRefOrGetter<boolean>

Whether the form is readonly. Components can read this to conditionally disable inputs.

isValid

ComputedRef<boolean | null>

Aggregate: true if all validations valid, false if any invalid, null if any unvalidated.

isValidating

ComputedRef<boolean>

Aggregate: true if any validation is in progress.

Methods

clear

() => void

Clear the entire registry

has

(id: ID) => boolean

Check if a ticket exists by ID

keys

() => readonly ID[]

Get all registered IDs

browse

(value: E["value"]) => ID[] | undefined

Browse for an ID(s) by value

lookup

(index: number) => ID | undefined

lookup a ticket by index number

get

(id: ID) => E | undefined

Get a ticket by ID

upsert

(id: ID, ticket?: Partial<Z>, event?: string) => E

Update or insert a ticket by ID

values

() => readonly E[]

Get all values of registered tickets

entries

() => readonly [ID, E][]

Get all entries of registered tickets

unregister

(id: ID) => void

Unregister a ticket by ID

reindex

() => void

Reset the index directory and update all tickets

move

(id: ID, toIndex: number) => E | undefined

Seek for a ticket based on direction and optional predicate

seek

(direction?: "first" | "last", from?: number, predicate?: (ticket) => boolean) => E | undefined

on

<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => void

Listen for registry events

off

<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => void

Stop listening for registry events

emit

<K extends Extensible<RegistryEventName>>(event: K, data: EventPayload<E, K>) => void

Emit an event with data

dispose

() => void

Clears the registry and removes all listeners

offboard

(ids: ID[]) => void

Offboard multiple tickets at once

batch

<R>(fn: () => R) => R

Execute operations in a batch, deferring cache invalidation and event emission until complete

register

(registration: Partial<Z> & { value) => E

Register a validation context with the form.

submit

(id?: ID | ID[]) => Promise<boolean>

Submit: validate specific fields or all.

reset

() => void

Reset all registered validations.

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/