Skip to main content

Form Validation

React-Forminate provides a robust validation system with multiple validation strategies, customizable error messages, and flexible validation triggers. This guide covers all aspects of form validation in the library.

Validation Basics

Required Fields

Mark a field as required and customize its error message:

{
fieldId: "username",
type: "text",
required: true,
requiredMessage: "Username is mandatory" // Custom message
}

Validation Triggers

Control when validation occurs:

const formData = {
formId: "myForm",
options: {
validateFieldsOnBlur: true // Default (true = validate on blur, false = validate on change)
},
fields: [
// your fields
]
}

Validation Types

Pattern Matching

Validate against regular expressions:

{
fieldId: "username",
type: "text",
validation: [
{
pattern: "^[a-zA-Z0-9_]{4,20}$",
message: "4-20 chars: letters, numbers, or underscores only."
}
]
}

Length Validation

For text fields:

validation: [
{
minLength: 3,
message: "Must be at least 3 characters"
},
{
maxLength: 50,
message: "Cannot exceed 50 characters"
}
]

Numeric Validation

For number fields:

validation: [
{
min: 18,
max: 100,
message: "Must be between 18 to 100"
},
{
pattern: "^[0-9]+$",
message: "Only numbers allowed"
}
]

OR

validation: [
{
min: 18,
message: "Must be at least 18"
},
{
max: 100,
message: "Cannot exceed 100"
},
{
pattern: "^[0-9]+$",
message: "Only numbers allowed"
}
]

Date Validation

For date fields:

validation: [
{
minDate: "2000-01-01",
maxDate: "2023-12-31",
message: "Must be after January 1, 2000 and before 2024"
}
]

OR

validation: [
{
minDate: "2000-01-01",
message: "Must be after January 1, 2000"
},
{
maxDate: "2023-12-31",
message: "Must be before 2024"
}
]

Array Validation

For checkbox groups and multi-selects:

validation: [
{
minItems: 1,
message: "Select at least one option"
},
{
maxItems: 3,
message: "Select no more than three options"
}
]

Custom Validation

Implement complex validation logic:

validation: [
{
custom: (value) => {
// Your validation logic
return value !== "forbidden";
},
message: "This value is not allowed"
}
]

Validation Strategies

React-Forminate uses a strategy pattern for validation. Here are all built-in strategies:

StrategyApplies ToDescription
patternText fieldsRegex pattern matching
minLengthText fieldsMinimum character length
maxLengthText fieldsMaximum character length
minNumber fieldsMinimum numeric value
maxNumber fieldsMaximum numeric value
minDateDate fieldsEarliest allowed date
maxDateDate fieldsLatest allowed date
minItemsArray fieldsMinimum selected items
maxItemsArray fieldsMaximum selected items
requiredAll fieldsField is mandatory
customAll fieldsCustom validation function

Advanced Validation

Conditional Validation

Show/hide fields based on other field values, and if the field is not visible, the validation engine automatically does not check that field:

{
fieldId: "spouseName",
type: "text",
visibility: {
dependsOn: "maritalStatus",
condition: "equals",
value: "married"
},
required: true
}

Custom Validation Strategies

Register custom validation strategies:

import { validationEngine } from "react-forminate";

class UniqueUsernameStrategy {
validate(value, rule) {
return api.checkUsernameAvailability(value)
.then(isAvailable => ({
isValid: isAvailable,
message: "Username already taken"
}));
}
}

validationEngine.registerStrategy("uniqueUsername", new UniqueUsernameStrategy());

Error Handling

Accessing Errors

Errors are available through the useForm hook:

const { errors } = useForm();

Displaying Errors

Errors are automatically displayed below each field, but you can customize:

import { DynamicForm, useForm } from "react-forminate";
import formData from "./formData.json"

const CustomErrorDisplay = () => {
const { errors } = useForm();

return (
<>
<div className="form-errors">
{Object.entries(errors).map(([fieldId, message]) => (
<div key={fieldId} className="error-message">
{message}
</div>
))}
</div>
<DynamicForm formData={formData}/>
</>
);
};

Manual Validation

Trigger validation manually:

const handleSubmit = (e) => {
e.preventDefault();
const isValid = validateForm();
if (isValid) {
// Submit form
}
};

Complete Example

import { DynamicForm } from "react-forminate";

const UserRegistrationForm = {
formId: "userRegistration",
options: {
validateFieldsOnBlur: true
},
fields: [
{
fieldId: "email",
type: "email",
label: "Email",
required: true,
validation: [
{
pattern: "^\\S+@\\S+\\.\\S+$",
message: "Enter a valid email address"
}
]
},
{
fieldId: "password",
type: "password",
label: "Password",
required: true,
validation: [
{
minLength: 8,
message: "Password must be at least 8 characters"
},
{
pattern: "^(?=.*[A-Z])(?=.*[0-9]).*$",
message: "Must contain at least one number and uppercase letter"
}
]
},
{
fieldId: "age",
type: "number",
label: "Age",
required: true,
validation: [
{
min: 18,
message: "You must be 18 or older"
},
{
max: 120,
message: "Enter a realistic age"
}
]
},
{
fieldId: "subscribe",
type: "checkbox",
label: "Subscribe to newsletter",
validation: [
{
custom: (value, { values }) => {
// Only require if email is provided
return !values.email || value === true;
},
message: "Subscription required for email users"
}
]
}
]
};

const RegistrationPage = () => (
<DynamicForm
formId={UserRegistrationForm.formId}
formData={UserRegistrationForm}
onSubmit={(values, isValid) => {
if (isValid) {
console.log("Submitting:", values);
}
}}
/>
);
Clicky