Built-in and custom validation rules for FieldCraft forms.
Required Fields
Set required: true on any question. The engine blocks section navigation until all required fields have values.
{ id: "name", type: "short_text", label: "Name", required: true }
Built-in Rules
Add validation rules to the validation array on any question:
{
id: "age",
type: "number",
label: "Age",
validation: [
{ type: "min", value: 18, message: "Must be at least 18" },
{ type: "max", value: 120, message: "Enter a valid age" },
],
}
| Rule Type | Value | Description |
|---|
min | number | Minimum value (numbers) or length (strings) |
max | number | Maximum value or length |
pattern | string (regex) | Must match regex pattern |
minLength | number | Minimum character count |
maxLength | number | Maximum character count |
Custom Validators
Register sync validators when creating the engine:
import { createEngine } from "@squaredr/fieldcraft-core";
const engine = createEngine(schema, {
validators: {
noSpam: (value) => {
if (typeof value === "string" && value.includes("http")) {
return "Links are not allowed";
}
return null; // valid
},
},
});
Reference them in the schema:
{
id: "comments",
type: "long_text",
label: "Comments",
validation: [{ type: "custom", validator: "noSpam" }],
}
Async Validators
For server-side checks (e.g., username availability):
const engine = createEngine(schema, {
asyncValidators: {
uniqueUsername: async (value) => {
const res = await fetch(`/api/check-username?q=${value}`);
const data = await res.json();
return data.available ? null : "Username is taken";
},
},
});
Error Display
Errors are stored as string[] per field in FormState.errors. The engine only shows errors after a field has been touched (blurred) or after a submit attempt.
const state = engine.getState();
// Check errors for a specific field
const emailErrors: string[] | undefined = state.errors["email"];
// Or use the engine helper
const errors = engine.getFieldError("email"); // string[] | undefined