createForm
Coordinates validation across multiple inputs. Provides submit(), reset(), and aggregate validity state.
Usage
Creating a Form
Create a form and register validation contexts. Each validation owns its rules for a single input:
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:
<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:
const form = createForm({ disabled: true })
form.disabled.value = false // Toggle at runtimeInjecting a Form Context
Use useForm to inject an existing form context provided by a parent component:
import { useForm } from '@vuetify/v0'
const form = useForm() // Returns undefined if no parent formContext / DI
Use createFormContext to share a form instance across a component tree:
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
| Option | Type | Default | Notes |
|---|---|---|---|
disabled | MaybeRefOrGetter<boolean> | false | When truthy, child components should disable interaction. Read via form.disabled |
readonly | MaybeRefOrGetter<boolean> | false | When truthy, child components should prevent editing. Read via form.readonly |
Architecture
createForm is a pure registry. Validations register with it for coordination:
Reactivity
Form-level state is fully reactive.
| Property/Method | Reactive | Notes |
|---|---|---|
isValid | Computed from all registered validations | |
isValidating | Computed from all registered validations | |
disabled | ShallowRef, read by components | |
readonly | ShallowRef, read by components |
Examples
Contact Form
A contact form with field validation using createValidation, demonstrating submit(), reset(), and aggregate isValid/isValidating state.
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.
Options
Properties
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.
Methods
move
(id: ID, toIndex: number) => E | undefinedSeek for a ticket based on direction and optional predicate
seek
(direction?: "first" | "last", from?: number, predicate?: (ticket) => boolean) => E | undefinedon
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidListen for registry events
off
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidStop listening for registry events
emit
<K extends Extensible<RegistryEventName>>(event: K, data: EventPayload<E, K>) => voidEmit an event with data
batch
<R>(fn: () => R) => RExecute operations in a batch, deferring cache invalidation and event emission until complete