FieldCraftDocsServicesBlogWork With Me →

Validation

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 TypeValueDescription
minnumberMinimum value (numbers) or length (strings)
maxnumberMaximum value or length
patternstring (regex)Must match regex pattern
minLengthnumberMinimum character count
maxLengthnumberMaximum 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