What is Validation?
Validation is the process of ensuring that data entered by users meets your application’s requirements. It’s like a quality control system for your forms that:- Prevents invalid data from being submitted
- Provides immediate feedback to users
- Reduces errors and improves data quality
- Enhances user experience by guiding correct input
How Validation Works
Validation Flow
When the user interacts with a form field (component), FormEngine Core performs the following actions:- Checks whether automatic validation is enabled for this field (enabled by default).
- If automatic validation is disabled for a field, then validation is not performed.
- Executes all validators specified for this field in the order of their sequence in the JSON array.
- If at least one of the validators returns a validation error, the validation error is localized (optionally) and displayed to the user.
Field Validation
Field validation is the most common type of validation - applying rules to individual form fields.Adding Validation to Fields
You can add validation to fields using JSON configuration.JSON Configuration
In JSON form definitions, add validation rules to the schema.validations array:MuiTextField. MuiTextField is a component that has a property
bound to data of type string. There are three validators for this component: required, email, and max. When the user enters data,
validation occurs. FormEngine Core will find three validators with keys required, email, max associated with the string type. It
will call these validators and display an error.
Live example
live
Built-in Validators Based on Zod
FormEngine Core includes a comprehensive set of validators powered by Zod. These validators are organized by data type.String Validators
String validators work with text inputs, textareas, and any component that accepts text values. Validators can accept arguments. A special argument for built-in validators ismessage, the error text that will be returned to the user.
The message argument is optional.
| Validator | Description | Example JSON |
|---|---|---|
required | Field must not be empty | {"key": "required", "args": {"message": "This field is required"}} |
nonEmpty | Field must not be empty (alias for required) | {"key": "nonEmpty", "args": {"message": "Cannot be empty"}} |
min | Minimum length | {"key": "min", "args": {"limit": 3, "message": "Must be at least 3 characters"}} |
max | Maximum length | {"key": "max", "args": {"limit": 100, "message": "Cannot exceed 100 characters"}} |
length | Exact length | {"key": "length", "args": {"length": 10, "message": "Must be exactly 10 characters"}} |
email | Valid email format | {"key": "email", "args": {"message": "Invalid email address"}} |
url | Valid URL format | {"key": "url", "args": {"message": "Invalid URL"}} |
uuid | Valid UUID format | {"key": "uuid", "args": {"message": "Invalid UUID"}} |
ip | Valid IP address (IPv4 or IPv6) | {"key": "ip", "args": {"message": "Invalid IP address"}} |
datetime | ISO datetime format | {"key": "datetime", "args": {"message": "Invalid datetime format"}} |
regex | Custom regular expression | {"key": "regex", "args": {"regex": "^[A-Z][a-z]+$", "message": "Must start with capital letter"}} |
includes | Contains substring | {"key": "includes", "args": {"value": "example", "message": "Must contain 'example'"}} |
startsWith | Starts with substring | {"key": "startsWith", "args": {"value": "Mr.", "message": "Must start with 'Mr.'"}} |
endsWith | Ends with substring | {"key": "endsWith", "args": {"value": ".com", "message": "Must end with '.com'"}} |
Number Validators
Number validators work with numeric inputs and selectors.| Validator | Description | Example JSON |
|---|---|---|
required | Field must contain a number | {"key": "required", "args": {"message": "This field is required"}} |
min | Minimum value | {"key": "min", "args": {"limit": 18, "message": "Must be at least 18"}} |
max | Maximum value | {"key": "max", "args": {"limit": 120, "message": "Cannot exceed 120"}} |
lessThan | Less than value | {"key": "lessThan", "args": {"value": 100, "message": "Must be less than 100"}} |
moreThan | Greater than value | {"key": "moreThan", "args": {"value": 0, "message": "Must be greater than 0"}} |
integer | Must be an integer | {"key": "integer", "args": {"message": "Must be a whole number"}} |
multipleOf | Multiple of value | {"key": "multipleOf", "args": {"value": 5, "message": "Must be a multiple of 5"}} |
Date Validators
Date validators work with date pickers and date inputs.| Validator | Description | Example JSON |
|---|---|---|
required | Field must contain a date | {"key": "required", "args": {"message": "Date is required"}} |
min | Minimum date | {"key": "min", "args": {"value": "2024-01-01", "message": "Cannot be before 2024"}} |
max | Maximum date | {"key": "max", "args": {"value": "2024-12-31", "message": "Cannot be after 2024"}} |
Array Validators
Array validators work with multi-selects, checkboxes, and repeaters.| Validator | Description | Example JSON |
|---|---|---|
required | Array must not be empty | {"key": "required", "args": {"message": "At least one item is required"}} |
nonEmpty | Array must not be empty | {"key": "nonEmpty", "args": {"message": "Cannot be empty"}} |
min | Minimum array length | {"key": "min", "args": {"limit": 1, "message": "Select at least one item"}} |
max | Maximum array length | {"key": "max", "args": {"limit": 5, "message": "Cannot select more than 5 items"}} |
length | Exact array length | {"key": "length", "args": {"length": 3, "message": "Must select exactly 3 items"}} |
Boolean Validators
Boolean validators work with checkboxes and switches.| Validator | Description | Example JSON |
|---|---|---|
required | Must be true (checked) | {"key": "required", "message": "This must be checked"} |
truthy | Must be true (checked) | {"key": "truthy", "message": "This must be checked"} |
falsy | Must be true (unchecked) | {"key": "falsy", "message": "This must be unchecked"} |
Time Validators
Time validators work with components whose data is time.| Validator | Description | Example JSON |
|---|---|---|
required | Field must contain a time | {"key": "required", "message": "Time is required"} |
Form Validation
Form validation allows you to validate the entire form or groups of fields together.Form-Level Validation
You can validate the entire form using thevalidate action:
Live example
live
validate action with failOnError: true will prevent the onSubmit action from running if any validation errors exist.
Conditional Validation
Conditional validation allows you to apply validation rules only when certain conditions are met.Using validateWhen Property
ThevalidateWhen property accepts a JavaScript expression that determines when the validation should run. An expression is essentially a
JavaScript statement that returns true or false. As input, it receives
the form parameter with all the information from the form.
Live example
live
Complex Conditional Validation
You can create complex validation logic that depends on multiple fields:Live example
live
Code Validation
Code validation allows you to write custom validation logic using JavaScript code. This is the most flexible validation option. The function body of this validator is stored in JSON.Code Validation Parameters
Thecode validator has access to these parameters:
value: The current field valueform: The complete form data object
true if validation passes, or false if validation fails.
Basic Code Validation
For example, we want to add a date validator so that the value in the field is greater than the current date. Here is a sample code:code validator with custom JavaScript logic:
Live example
live
Cross-Field Validation with Code
Validate relationships between multiple fields:Live example
live
Custom Validation
Custom validation allows you to create reusable validators that can be registered and used across your application. Custom validators are passed to the FormViewer component’s props via prop validators, and custom validators are connected to form components as well as embedded validators via JSON forms, but with the addition of thecustom type.
Registering Custom Validators
Register custom validators when initializing FormEngine Core:Using Custom Validators
Use registered custom validators in your form JSON:Live example
live
Custom Validator with Parameters
Create parameterized custom validators:Live example
live
Automatic Validation
How Automatic Validation Works
By default, FormEngine Core performs automatic field validation when the value of this field changes.Disabling Automatic Validation
You can disable automatic validation for specific fields using the autoValidate property:autoValidate: false, the field will only be validated when explicitly triggered (e.g., during validate action).
Validation Error Display
Default Error Display
FormEngine Core automatically displays validation errors next to the corresponding field. To display errors in the form, FormEngine Core uses the component specified in the JSON file of the form in the errorType field. An example for MUI components:Custom Error Display
You can configure the error display by specifying the errorProps field in JSON. This field describes the properties that will be passed to the component specified in theerrorType field.
Showing All Validation Errors
By default, FormEngine Core displays the first validation error for a component, even if the component has multiple validators specified. You can configureFormViewer so that it displays all validation errors for the component at once. To do this, set the value of the
showAllValidationErrors property to true.
Live example
live
Advanced Form Validation
Advanced form validation allows you to validate the entire form data with custom logic that can check relationships between multiple fields, perform complex business rules, and validate data consistency across the entire form.Form Validator in JSON (formValidator)
You can define a form-level validator directly in the JSON form definition using the formValidator field. This validator runs JavaScript code that has access to all form data and returns validation errors for any field. The form validation function accepts theformData
argument as input, which is an object with form data. Below is an example of such a function (only the function body is stored in JSON):
Basic Example
Live example
live
Form Validator Function Signature
TheformValidator code should be a JavaScript function body that:
- Receives a
formDataparameter containing all form field values - Returns an object where:
- Keys are field names
- Values are error messages for those fields
- Returns an empty object
{}orundefinedif validation passes
External Form Validators via FormViewer (formValidators)
For more complex validation scenarios or when you need to reuse validation logic across multiple forms, you can provide external form validators through the formValidators property of the FormViewer component.Registering External Form Validators
Live example
live
Combining JSON Form Validator with External Validators
When bothformValidator (in JSON) and formValidators (external) are provided, FormEngine Core runs all validators and combines their
results:
Form Validator Execution Order
When form validation is triggered (e.g., by thevalidate action), FormEngine Core executes validators in this order:
- Field-level validators: Each field’s individual validators run
- JSON formValidator: The validator defined in the JSON
formValidatorfield runs - External formValidators: All validators in the
formValidatorsarray run
false, in which
case only the first error is shown).
Live example
live
Error Handling in Form Validators
Form validators should handle errors gracefully:Best Practices for Form Validators
- Keep validators focused: Each validator should check a specific aspect of the form
- Use async validators for server-side checks: Email availability, username uniqueness, etc.
- Provide clear error messages: Tell users exactly what needs to be fixed
- Validate early: Use field-level validation for simple checks, form-level for complex relationships
- Test edge cases: Empty forms, partial data, invalid types
- Performance considerations: Avoid expensive operations in synchronous validators
Best Practices
1. Provide Clear Error Messages
- Do: “Password must be at least 8 characters and include a number”
- Don’t: “Invalid password”
2. Validate Early and Often
- Use
autoValidate: true(default) for real-time feedback
3. Use Appropriate Validator Types
- Use built-in validators when possible (more efficient)
- Use
codevalidators for complex business logic - Use custom validators for reusable validation patterns
4. Test Edge Cases
- Empty values
- Null/undefined values
- Extremely long values
- Special characters
- Boundary conditions (min/max values)
5. Performance Considerations
- Avoid complex calculations in
validateWhenconditions
Troubleshooting
Validation Not Working
- Check schema type: Ensure
schema.typematches the field’s data type - Verify validator keys: Check for typos in validator
keynames - Check autoValidate: If
autoValidate: false, validation only triggers manually
Custom Validators Not Recognized
- Verify registration: Ensure custom validators are registered before form rendering
- Check type: Custom validators need
"type": "custom"in JSON - Verify parameters: Ensure required parameters are provided
Conditional Validation Not Executing
- Check
validateWhensyntax: Ensure JavaScript expression is valid - Verify field references: Use
form.data['fieldName']to reference other fields - Test condition separately: Log the condition result to debug
Error Messages Not Displaying
- Check error wrapper: Ensure ErrorWrapper components are properly configured
- Verify CSS: Custom error styles might conflict with default styles
- Check form configuration:
showAllValidationErrorsmight affect display
For more information:
Next steps
- Form Submission — Handle form submission and process submitted data
- Conditional Logic — Apply validation rules only when certain conditions are met