Skip to main content

Validation

Formitiva provides a flexible validation system supporting:

  • Built-in (declarative) validation
  • Field-level custom validation
  • Form-level validation
  • Synchronous and asynchronous handlers
  • Configurable validation timing

Built-in Validation

Built-in validators are defined declaratively in the field schema.
They work out-of-the-box in the renderer and are supported by the visual builder.

Supported Rules​

Required​

Property required indicate the value is required and can't be empty. Default is false.

{
"required": true
}

Numeric Fields​

PropertyDescription
minMinimum value
maxMaximum value
minInclusiveInclude min in validation (default: true)
maxInclusiveInclude max in validation (default: true)
stepStep increment (for steppers)

Text / Multiline​

PropertyDescription
minLengthMinimum character length
maxLengthMaximum character length

Arrays (int & float)​

PropertyDescription
minCountMinimum number of items
maxCountMaximum number of items

Date​

PropertyDescription
minDateEarliest allowed date
maxDateLatest allowed date

Pattern (Regex)​

PropertyDescription
patternRegex string
patternErrorMessageCustom validation message
  • Example:
{
"name": "zip",
"type": "text",
"pattern": "^[0-9]{5}$",
"patternErrorMessage": "Please enter a 5-digit ZIP code"
}

Built-in Validation Notes​

  • Built-in validators run before custom validators.
  • When built-in validation fail, error returned and custom validation is skipped.

Field Validation Mode

The fieldValidationMode prop controls when field validation runs.

Modes​

ModeDescription
"onEdit"Validate while editing. Errors appear immediately.
"onBlur"Validate when edit lose focus.
"onSubmission"Validate only on submit. Submission is blocked if invalid.
"realTime"Deprecated. Same as "onEdit".

Example​

React​

// Validate during editing
<Formitiva definitionData={definition} instance={instance} fieldValidationMode="onEdit" />

// Validate when input loses focus
<Formitiva definitionData={definition} instance={instance} fieldValidationMode="onBlur" />

// Validate only on form submit
<Formitiva definitionData={definition} instance={instance} fieldValidationMode="onSubmission" />

Vue​

<!-- Validate during editing -->
<Formitiva :definition-data="definition" :instance="instance" field-validation-mode="onEdit" />

<!-- Validate when input loses focus -->
<Formitiva :definition-data="definition" :instance="instance" field-validation-mode="onBlur" />

<!-- Validate only on form submit -->
<Formitiva :definition-data="definition" :instance="instance" field-validation-mode="onSubmission" />

Angular​

<!-- Validate during editing -->
<fv-formitiva [definitionData]="definition" [instance]="instance" fieldValidationMode="onEdit"></fv-formitiva>

<!-- Validate when input loses focus -->
<fv-formitiva [definitionData]="definition" [instance]="instance" fieldValidationMode="onBlur"></fv-formitiva>

<!-- Validate only on form submit -->
<fv-formitiva [definitionData]="definition" [instance]="instance" fieldValidationMode="onSubmission"></fv-formitiva>

Vanilla JS​

import { Formitiva } from '@formitiva/vanilla';

// Validate during editing
new Formitiva({ definitionData: definition, instance, fieldValidationMode: 'onEdit' }).mount(el);

// Validate when input loses focus
new Formitiva({ definitionData: definition, instance, fieldValidationMode: 'onBlur' }).mount(el);

// Validate only on form submit
new Formitiva({ definitionData: definition, instance, fieldValidationMode: 'onSubmission' }).mount(el);

Field-Level Validation

Field-level validators validate a single field.

Use cases:

  • Format validation
  • Value constraints

Registration​

  1. Register a handler in your application.
  2. Reference it in the field definition.

Handler Signature​

export type FieldCustomValidationHandler = (
fieldName: string,
value: FieldValueType | unknown,
t: TranslationFunction,
) => string | undefined;
  • Return Value
    • Return a string when a validation error occurs.
      The string represents the error message (preferably localized using t).
    • Return undefined when validation succeeds (no error).

registerFieldCustomValidationHandler signature​

export function registerFieldCustomValidationHandler(
category: string, // Category name. Normally definition name, also can be `math`, `business`, ...
name: string,
fn: FieldCustomValidationHandler
): void
  • Parameters
    • category : category name to group same functionality handlers. Normally it is definition name, can also be other names: math, business, ...
    • name : handler name
    • fn : field custom validation handler(function)

Example​

registerFieldCustomValidationHandler('math', 'evenNumber', (fieldName, value, t) => {
const number = Number(value);
if (Number.isFinite(number) || value % 2 !== 0) {
return t('Value must be an even number');
}
return undefined;
});

Field definition:​

The optional validationHandlerName of each property specifies the registered validation handler

validationHandlerName: string | [string, string]
  • Note:
    • string : handler name, category name is default to definition name
    • [string, string] : first value is category name and second value is handler name
{
"name": "evenNumber",
"type": "int",
"validationHandlerName": ["math", "evenNumber"]
}

Field-Level Notes​

  • Typically triggered on blur or change.
  • Prefer returning localized message keys via t().
  • For performance consideration, field level validation is synchronous process, if a field needs asynchronous validation, use form level validation to check it.

Field Type Validation

When you define a new type of component, you can define a type validation for this component.

Handler signature​

export type FieldTypeValidationHandler = (
field: DefinitionPropertyField,
input: FieldValueType,
t: TranslationFunction,
) => string | undefined;
  • Paramter
    • field : field definition
    • input : the field input value for validation
    • t : translation function
  • Return
    • Return a string when a validation error occurs.
      The string represents the error message (preferably localized using t).
    • Return undefined when validation succeeds (no error).

Registration​

export function registerFieldTypeValidationHandler(
name: string,
fn: FieldTypeValidationHandler
): void
  • Parameters
    • name : the new component type name, used to specify the type property in definition
    • fn : type validation handler

Example​

Please check custom component document for the example Type Validation

Form-Level Validation

Form-level validators validate multiple fields together and support asynchronous validation.

Use cases:

  • Cross-field validation (e.g., confirm password, compare values,...)
  • Combined constraints
  • Server-side validation requiring full form context

Registration​

  1. Register a form validation handler.
  2. Reference it at the form root using validationHandlerName.

Handler signature​

export type FormValidationHandler = (
valuesMap: Record<string, FieldValueType | unknown>,
t: TranslationFunction,
) => string[] | Promise<string[] | undefined> | undefined;
  • Parameters
    • valuesMap: map of property name to value
    • t : translation function, use for localize error messages
  • Returns
    string[] : error messsages when there are errors undefined: validation success

Registration signamture​

export function registerFormValidationHandler(
name: string,
fn: FormValidationHandler
): void
  • Parameter
    • name : form validation handler name
    • fn : form validation handler
  • Return: void

Example​

  • Define the Validation Function

    const uniqueEmailCheck = async (
    valuesMap: Record<string, any>,
    t: TranslationFunction
    ) => {
    const errors: Record<string, string> = {};

    if (valuesMap.email && !(await api.isEmailUnique(valuesMap.email))) {
    errors.Add(t('Email already in use'));
    }

    return Object.keys(errors).length ? { errors } : undefined;
    };
  • Register the Validation Function

    registerFormValidationHandler('uniqueEmailCheck', uniqueEmailCheck);
  • Form definition: Specify the uniqueEmailCheck in defintion root validationHandlerName

    {
    "name": "signup",
    "displayName": "Sign up",
    "validationHandlerName": "uniqueEmailCheck",
    "properties": [/* ... */]
    }

Form-Level Notes​

  • Runs on submit by default.
  • Can be triggered earlier via custom hooks.
  • Return field-mapped errors for better UI integration.
  • Use t() for localization.

Sync/Async Validation

Field-level handler is synchronous and Form-level handlers can be asynchronous.

Best Practices​

  • For performance consideration, field validation process simple single field validation.
  • Put time consuming and asynchronous validation in form validation

Error Messages & Localization

Validation messages should be:​

  • Consistent
  • Localizable
  • Centralized

Localiztion dictionary​

In formitiva, dictionary is used for translate error messages.

  • Localization can be specify a dictionary file in defintion with property localization
  • The dictionary file is put in public/locales/{lang}

Recommendations​

  • Prefer message keys resolved via t().
  • Use schema-level message properties (e.g., patternErrorMessage).

Validation Execution Order

  1. Built-in field validators
  2. Custom field-level validators
  3. Form-level validators (typically on submit)