Skip to main content
Vuetify0 is now in beta!
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.

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.
Was this page helpful?

Ctrl+/