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

createValidation

Per-input validation with reactive rules, async validation, and Standard Schema support.


IntermediateApr 5, 2026

Usage

Standalone

Create a validation instance with rules. Pass a value source so validate() reads from it automatically:

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

const email = shallowRef('')
const validation = createValidation({
  value: email,
  rules: [
    v => !!v || 'Required',
    v => /^.+@\S+\.\S+$/.test(String(v)) || 'Invalid email',
  ],
})

await validation.validate()

console.log(validation.errors.value)    // ['Required', 'Invalid email']
console.log(validation.isValid.value)   // false

validation.reset()

Explicit Value

Pass the value directly to validate() instead of storing a value source:

ts
const validation = createValidation({
  rules: [v => !!v || 'Required'],
})

await validation.validate('')       // validate with empty string
await validation.validate('hello')  // validate with 'hello'

With Rule Aliases

When a rules context is provided via createRulesPlugin or createRulesContext, alias strings resolve automatically:

ts
const validation = createValidation({
  rules: ['required', 'slug'],
})

With Standard Schema

Any Standard Schema↗-compliant library works without an adapter — pass the schema object directly and it’s auto-detected:

zod
import { z } from 'zod'

const validation = createValidation({
  rules: [z.coerce.number().int().min(18, 'Must be 18+')],
})

Dynamic Rules

Register rules individually after creation:

ts
const validation = createValidation()

validation.register(v => !!v || 'Required')
validation.register(v => /^.+@\S+\.\S+$/.test(String(v)) || 'Invalid email')

Use onboard() to register multiple rules at once:

ts
validation.onboard([
  v => !!v || 'Required',
  v => v.length >= 8 || 'Min 8 characters',
  v => /[A-Z]/.test(String(v)) || 'Must contain uppercase',
])

Enabling and Disabling Rules

Each rule is a ticket with selection methods from createGroup. The enroll option (default true) controls whether newly registered rules are active immediately. Set enroll: false to register rules in an inactive state:

ts
const validation = createValidation({
  rules: [
    v => !!v || 'Required',
    v => /^.+@\S+\.\S+$/.test(String(v)) || 'Invalid email',
  ],
})

// Disable the email format rule
const [, format] = [...validation.values()]
format.unselect()

await validation.validate('')
// Only 'Required' runs — format rule is inactive

// Re-enable it
format.select()

Silent Validation

Check validity without updating the UI:

ts
const valid = await validation.validate('', true) // silent = true
// validation.errors.value is unchanged
// validation.isValid.value is unchanged

Auto-Registration with Forms

When created inside a component with a parent form context, createValidation auto-registers with the form. The form can then coordinate submit and reset across all registered validations. Cleanup happens automatically via onScopeDispose:

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

  // Parent provides form context via createFormContext or createFormPlugin
  // This validation auto-registers with it
  const email = shallowRef('')
  const validation = createValidation({
    value: email,
    rules: ['required', 'email'],
  })
</script>

Architecture

createValidation extends createGroup with per-input validation state. Each ticket is a rule. When a parent form context exists, it auto-registers:

Validation Architecture

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

Validation Architecture

Race Safety

Async validation uses a generation counter to prevent stale results. If a newer validation starts before an older one completes, the older result is discarded.

Reactivity

Context-level state is fully reactive. Rule tickets inherit selection reactivity from createGroup.

Property/MethodReactiveNotes
errorsShallowRef array of error strings
isValidShallowRef (null/true/false)
isValidatingShallowRef boolean
selectedIdsReactive Set of active rule IDs
ticket.isSelectedRef boolean per rule

Examples

Async Validation

Username availability check with async rules and generation-based race safety. Demonstrates isValidating spinner, error display, and tri-state isValid.

Validation State

isValid: null

isValidating: false

errors: 0

rules: 4 (4 active)

Try: "admin", "root", "test" (taken) or "hello" (available)

Enabling and Disabling Rules

Toggle individual validation rules on/off at runtime using the selection API inherited from createGroup.

Active Rules

4/4 rules active · Only selected rules run during validation.

API Reference

The following API details are for the createValidation composable.

Functions

createValidation

(_options?: ValidationOptions) => ValidationContext<ValidationTicketInput, ValidationTicket<ValidationTicketInput>>

Creates a per-input validation instance. Built on `createGroup` — each registered rule becomes a ticket that can be enabled/disabled via selection methods (`select`, `unselect`, `toggle`). Only selected (active) rules run during validation.

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

Disabled state for the entire model instance

Default: false

enroll

MaybeRefOrGetter<boolean> | undefined

Auto-select tickets on registration

Default: true

multiple

MaybeRefOrGetter<boolean> | undefined

Allow multiple tickets to be selected simultaneously

Default: false

mandatory

MaybeRefOrGetter<boolean | "force"> | undefined

Controls mandatory selection behavior: - `false` (default): No mandatory selection enforcement - `true`: Prevents deselecting the last selected item - `'force'`: Automatically selects the first non-disabled item on registration

rules

RuleInput[] | undefined

Initial rules to register.

value

unknown

Value source for validate() when called without arguments.

Properties

collection

ReadonlyMap<ID, E>

The collection of tickets in the registry

size

number

The number of tickets in the registry

selectedIds

Reactive<Set<ID>>

Set of currently selected ticket IDs

selectedItems

ComputedRef<Set<E>>

Computed Set of selected ticket instances

selectedValues

ComputedRef<Set<E["value"] extends Ref<infer U, infer U> ? U : E["value"]>>

Computed Set of selected ticket values

disabled

MaybeRefOrGetter<boolean>

Disabled state for the entire model instance

multiple

MaybeRefOrGetter<boolean>

Whether the selection allows multiple selections

selectedIndexes

ComputedRef<Set<number>>

mixedIds

Reactive<Set<ID>>

Set of mixed/indeterminate ticket IDs

mixedItems

ComputedRef<Set<E>>

Set of mixed/indeterminate ticket instances

isNoneSelected

ComputedRef<boolean>

Whether no items are currently selected

isAllSelected

ComputedRef<boolean>

Whether all selectable (non-disabled) items are selected

isMixed

ComputedRef<boolean>

Whether some but not all selectable items are selected

errors

ShallowRef<string[]>

Current validation error messages.

isValid

ShallowRef<boolean | null>

Tri-state: null (not validated), true (valid), false (invalid).

isValidating

ShallowRef<boolean>

Whether async 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

selected

(id: ID) => boolean

Check if a ticket is currently selected

apply

(values: unknown[], options?: { multiple?) => void

Apply external values to the model

mandate

() => void

Mandate selected ID based on "mandatory" option

select

(ids: ID | ID[]) => void

Select one or more Tickets by ID

unselect

(ids: ID | ID[]) => void

Unselect one or more Tickets by ID

toggle

(ids: ID | ID[]) => void

Toggle one or more Tickets ON and OFF by ID

mix

(ids: ID | ID[]) => void

Set one or more Tickets to mixed/indeterminate state by ID

unmix

(ids: ID | ID[]) => void

Clear mixed/indeterminate state from one or more Tickets by ID

mixed

(id: ID) => boolean

Check if a ticket is in mixed/indeterminate state by ID

selectAll

() => void

Select all selectable (non-disabled) items

unselectAll

() => void

Unselect all items (respects mandatory option)

toggleAll

() => void

Toggle between all selected and none selected

register

(rule: RuleInput | Partial<Z>) => E

onboard

(rules: (RuleInput | Partial<Z>)[]) => E[]

validate

(value?: unknown, silent?: boolean) => Promise<boolean>

Run validation against all active (selected) rules.

reset

() => void

Reset errors and validation state. Does not affect rule selection.

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/