Show and hide fields based on previous answers.
Any question or section can include a showIf property. When present, the engine evaluates the condition against current form values and hides the field when it returns false. Hidden fields are excluded from validation and submission.
Basic Condition
A leaf condition references a field, an operator, and a comparison value:
{
id: "company_name",
type: "short_text",
label: "Company Name",
showIf: { field: "employment_status", operator: "eq", value: "employed" },
}
Operators
All 16 operators use camelCase:
| Operator | Description | Example Value |
|---|
eq | Strict equality | "yes" |
neq | Not equal | "no" |
gt | Greater than | 18 |
gte | Greater than or equal | 18 |
lt | Less than | 100 |
lte | Less than or equal | 100 |
in | Value is in array | ["a", "b"] |
notIn | Value is not in array | ["x", "y"] |
exists | Field has a value | none |
notExists | Field is empty/null/undefined | none |
contains | String includes substring | "admin" |
notContains | String does not include | "spam" |
startsWith | String starts with | "https" |
endsWith | String ends with | ".com" |
between | Value in range [min, max] | [18, 65] |
matches | Regex match | "^[A-Z]" |
Combining Conditions
Use combine with a conditions array to join multiple checks. The default combine mode is "AND".
// Show only if age >= 18 AND country is US
showIf: {
combine: "AND",
conditions: [
{ field: "age", operator: "gte", value: 18 },
{ field: "country", operator: "eq", value: "US" },
],
}
// Show if role is admin OR department is engineering
showIf: {
combine: "OR",
conditions: [
{ field: "role", operator: "eq", value: "admin" },
{ field: "department", operator: "eq", value: "engineering" },
],
}
Nested Groups
Conditions can be nested to any depth:
showIf: {
combine: "OR",
conditions: [
{ field: "role", operator: "eq", value: "admin" },
{
combine: "AND",
conditions: [
{ field: "department", operator: "eq", value: "sales" },
{ field: "years_experience", operator: "gte", value: 5 },
],
},
],
}
This reads: "Show if role is admin, OR (department is sales AND 5+ years experience)."
Section Visibility
Sections support the same showIf. A hidden section is skipped entirely during navigation and excluded from progress calculations.
{
id: "employer_details",
title: "Employer Details",
showIf: { field: "employment_status", operator: "eq", value: "employed" },
questions: [
{ id: "company", type: "short_text", label: "Company" },
{ id: "job_title", type: "short_text", label: "Job Title" },
],
}
Conditional Required & Disabled
The required and disabled properties also accept a condition expression instead of a plain boolean:
{
id: "spouse_name",
type: "short_text",
label: "Spouse Name",
// Required only when marital status is "married"
required: { field: "marital_status", operator: "eq", value: "married" },
}
{
id: "referral_code",
type: "short_text",
label: "Referral Code",
// Disabled when source is not "referral"
disabled: { field: "source", operator: "neq", value: "referral" },
}
Engine API
Query visibility at runtime through the engine:
const engine = createEngine(schema);
// All visible sections (hidden ones filtered out)
const sections = engine.getVisibleSections();
// Visible fields within a specific section
const fields = engine.getVisibleFields("personal_info");
// Check a single field
const visible = engine.isFieldVisible("company_name");
const required = engine.isFieldRequired("spouse_name");
const disabled = engine.isFieldDisabled("referral_code");
How Hidden Fields Behave
- Excluded from validation — a required hidden field does not block submit.
- Excluded from progress calculations.
- Their values are preserved in state. If a field is hidden then shown again, its previous value is restored.
- Visibility is recalculated on every value change.
TypeScript Types
import type { ConditionExpression, ConditionOperator } from "@squaredr/fieldcraft-core";
// Leaf condition
const leaf: ConditionExpression = {
field: "age",
operator: "gte",
value: 18,
};
// Group condition
const group: ConditionExpression = {
combine: "AND",
conditions: [leaf, { field: "country", operator: "eq", value: "US" }],
};