Skip to main content

Validation

Every field accepts a validation object that defines constraints for that field.

FieldValidation Interface

interface FieldValidation<T = unknown> {
required?: boolean | string;
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
pattern?: RegExp;
custom?: (value: T, formValues: Record<string, unknown>) => string | null;
asyncCustom?: (
value: T,
formValues: Record<string, unknown>,
) => Promise<string | null>;
}

Required Fields


Length Constraints

minLength: 3, maxLength: 20

maxLength: 200


Pattern (Regex)

{
name: 'zipCode',
type: 'text',
label: 'ZIP Code',
validation: {
required: true,
pattern: /^\d{5}(-\d{4})?$/,
},
},

Custom Synchronous Validator

The custom function receives the field value and all form values, enabling cross-field rules:

{
name: 'confirmPassword',
type: 'password',
label: 'Confirm Password',
validation: {
required: true,
custom: (value, allValues) => {
if (value !== allValues.password) {
return 'Passwords do not match';
}
return null; // null means valid
},
},
dependsOn: ['password'],
}

Async Validator

For server-side checks (e.g. username availability):

{
name: 'username',
type: 'text',
label: 'Username',
validation: {
required: true,
minLength: 3,
asyncCustom: async (value) => {
const taken = await checkUsernameAvailability(value as string);
return taken ? 'Username is already taken' : null;
},
},
}
note

asyncCustom is triggered on blur. A spinner is shown while the check runs.


Validation Summary

RuleTypeNotes
requiredboolean | stringFails if value is empty/null/undefined
minnumberNumeric minimum
maxnumberNumeric maximum
minLengthnumberString character minimum
maxLengthnumberString character maximum
patternRegExpRegex test
custom(v, all) => string | nullSync cross-field validation
asyncCustomasync (v, all) => string | nullAsync server-side validation