Atlas Forms
Complete Validation Reference
A consolidated quick-reference covering all validation rules, the ValidationEngine API, common patterns, and a troubleshooting guide.
All Built-In Rules at a Glance
| Rule | Companion Message Property | Control Types |
|---|---|---|
required: true | requiredMessage | All |
minLength: n | minLengthMessage | text, textarea, password, url |
maxLength: n | maxLengthMessage | text, textarea, password, url |
min: n | minMessage | number |
max: n | maxMessage | number |
email: true | emailMessage | email, text |
url: true | urlMessage | url, text |
pattern: "regex" | patternMessage | text, textarea, email |
minDate: "date" | minDateMessage | date, datetime |
maxDate: "date" | maxDateMessage | date, datetime |
matchesField: "id" | matchesFieldMessage | text, password, email |
minSelections: n | minSelectionsMessage | multiselect |
maxSelections: n | maxSelectionsMessage | multiselect |
minRows: n | minRowsMessage | data-table |
maxRows: n | maxRowsMessage | data-table |
fileTypes: [...] | fileTypesMessage | file-upload |
maxFileSizeMb: n | maxFileSizeMbMessage | file-upload |
requiredWhen: "expr" | requiredMessage | All |
validateWhen: "expr" | — | All |
revalidateOnChange: [...] | — | All |
ValidationEngine API
import { ValidationEngine } from '@atlas-forms/validation-js';
const engine = new ValidationEngine();
// Validate a single field
const result = await engine.validateField(
fieldId: string,
value: any,
validationConfig: ValidationConfig,
allValues: Record<string, any>
);
// Validate all fields in the form
const results = await engine.validateAll(
controls: FormControl[],
values: Record<string, any>
);
// Returns: Record<string, ValidationResult>
// Check if the form is valid
const isValid = engine.isFormValid(results);
// Get all error messages
const errors = engine.getErrors(results);
// Returns: Array<{ fieldId: string; message: string }>
Common Validation Patterns
Registration Form
[
{
"id": "username",
"type": "text",
"label": "Username",
"validation": {
"required": true,
"minLength": 3, "maxLength": 30,
"pattern": "^[a-zA-Z0-9_\\-]+$",
"customRule": { "name": "usernameAvailable", "async": true,
"message": "Username is already taken" }
}
},
{
"id": "email",
"type": "email",
"label": "Email Address",
"validation": {
"required": true, "email": true,
"customRule": { "name": "emailAvailable", "async": true,
"message": "An account with this email already exists" }
}
},
{
"id": "password",
"type": "password",
"label": "Password",
"validation": { "required": true, "minLength": 12 }
},
{
"id": "confirm-password",
"type": "password",
"label": "Confirm Password",
"validation": {
"required": true,
"matchesField": "password",
"matchesFieldMessage": "Passwords do not match",
"revalidateOnChange": ["password"]
}
}
]
Troubleshooting Guide
| Problem | Cause | Fix |
|---|---|---|
| Validator not found error | Validator name not registered before form renders | Call registerAllValidators() before ReactDOM.render() |
| Cross-field rule not re-running | Missing revalidateOnChange on dependent field | Add "revalidateOnChange": ["source-field-id"] |
| Async validator runs on every keystroke | autoValidate: true without debounce in validator | The engine debounces automatically; if still flooding, check if validator is marked async: true |
| Required rule fires on hidden field | Field is hidden by visibilityRule but still validated | Add matching validateWhen expression to skip validation when hidden |
| Error message not appearing | Field not touched and validateOn: "blur" | Use autoValidate: true or click another field to trigger blur validation |
| Inline expression validator always passes | Expression syntax error — returns undefined (truthy) | Test expression in browser console with eval(); check value and allValues variable names |