Validation

Validate forms with rules from the schema, custom error messages and your own checks.

SForm builds its validation from the schema, so the rules that describe your data also check it. Errors appear below each field, and submit is only emitted once the form is valid.

Rules from the schema

Standard JSON Schema keywords become validation rules:

  • required on an object makes those properties mandatory.
  • minLength, maxLength and pattern check strings.
  • format checks strings such as email, uri, date or date-time.
  • minimum, maximum and multipleOf check numbers.
  • minItems, maxItems and uniqueItems check arrays.
  • enum and const limit a field to fixed values.

Submit the form below without filling it in to see the errors:

optional
<script setup lang="ts">
const schema = ref({
  type: 'object',
  required: [
    'name',
    'email'
  ],
  properties: {
    name: {
      title: 'Name',
      type: 'string',
      minLength: 2,
      default: ''
    },
    email: {
      title: 'Email',
      type: 'string',
      format: 'email',
      default: ''
    },
    age: {
      title: 'Age',
      type: 'integer',
      minimum: 18
    }
  }
})
const model-value = ref({
  name: '',
  email: ''
})
</script>

<template>
  <SForm :model-value="model-value" :schema="schema" />
</template>

The schema is converted to a Yup schema by json-schema-yup-transformer, which lists every supported keyword.

Custom error messages

Pass jsonSchemaYupTransfromer in the options prop to change error messages. Under errors, nest messages by property path and keyword, or use defaults to set one message per keyword for the whole form.

<script lang="ts" setup>
import type { Config } from '@ederzeel/json-schema-yup-transformer'

const jsonSchemaYupTransfromer: Config = {
  errors: {
    defaults: {
      required: ([_key, { title }]) => `${title} is required`,
      format: ([_key, { title, format }]) => `${title} is not a valid ${format}`
    },
    guardian: {
      email: {
        required: 'We need an email address to reach a guardian'
      }
    }
  }
}
</script>

<template>
  <SForm v-model="state" :schema="schema" :options="{ jsonSchemaYupTransfromer }" />
</template>

A message is either a string or a function. A function gets the property's key and its schema, so one message can use the field's title.

The option is spelled jsonSchemaYupTransfromer, with "Transfromer".

Custom validation

For checks that JSON Schema can't express, pass customValidation in options. Each entry names a field by its dot path, a message, and a validate function that receives the whole form value:

import type { CustomValidation } from '#schema-form-types'

const customValidation: CustomValidation[] = [
  {
    field: 'misc.permission',
    message: 'Permission is required',
    validate: state => state.misc.permission === true
  }
]
<SForm v-model="state" :schema="schema" :options="{ customValidation }" />

Custom validation runs together with the rules from the schema: when the form is submitted, while the user edits a field, and when a renderer validates a group of fields with validateFields, like the next button of a multi-step form. A failing check blocks submit and shows its message on the field.