Skip to main content

Conditional Fields

Show, hide, enable, disable, and dynamically require fields based on other field values or runtime context.

How it works​

Rules are defined in buildForm and evaluated synchronously on every value change. A rule has two parts:

  • when — a condition expression
  • an effect — what happens when the condition is true (show, hide, require, disable, etc.)

Show/hide a field​

import { buildForm, field, layout, rule, fieldRef } from "formwright/schema";

const accountType = field.select("accountType", {
label: "Account type",
options: [
{ value: "individual", label: "Individual" },
{ value: "company", label: "Company" },
],
});

const companyName = field.text("companyName", { label: "Company name" });

const form = buildForm({
form: defineForm({ id: "account" }),
fields: [accountType, companyName],
layout: layout.stack("root", [
layout.field(accountType),
layout.field(companyName),
]),
rules: [
rule.when(fieldRef(accountType).eq("company")).show(companyName),
rule.when(fieldRef(accountType).neq("company")).hide(companyName),
],
});

companyName starts hidden. It appears when accountType is set to "company".

Conditionally require a field​

rules: [
rule.when(fieldRef(accountType).eq("company")).require(companyName),
]

This marks the field required at runtime. Formwright wires this into React Hook Form validation automatically.

Disable a field​

rules: [
rule.when(fieldRef(status).eq("locked")).disable(editableField),
]

Set a value when a condition is met​

rules: [
rule.when(fieldRef(country).eq("us")).setValue(currency, "USD"),
]

Multiple conditions with and / or​

import { rule, fieldRef } from "formwright/schema";
import type { RuleExpression } from "formwright/schema";

const condition: RuleExpression = {
and: [
fieldRef(accountType).eq("company"),
fieldRef(employeeCount).gt(50),
],
};

rules: [
rule.when(condition).show(enterprisePlanField),
]

Reference runtime context​

Pass arbitrary context to createFormRuntime and reference it in rules with contextRef:

import { contextRef } from "formwright/schema";

const runtime = createFormRuntime({
form,
plugins: registerBasicPlugins(),
context: { mode: "view" },
});

// In rules:
rules: [
rule.when(contextRef("mode").eq("view")).disable(editableField),
]

What happens to hidden field values​

By default, hidden field values are kept in the form state and included in the submit payload. Change this with hiddenFieldPolicy on FormRuntimeProvider:

// Clear hidden values from the payload:
<FormRuntimeProvider runtime={runtime} hiddenFieldPolicy="clear">

// Unregister fields from RHF when hidden:
<FormRuntimeProvider runtime={runtime} hiddenFieldPolicy="unregister">

// Keep hidden values (default):
<FormRuntimeProvider runtime={runtime} hiddenFieldPolicy="keep">

Choose "clear" when hidden fields should not appear in the submit payload. Choose "keep" when you need to preserve hidden values (e.g., for re-appearing fields that should retain their last value).

Available operators​

OperatorUsage
.eq(value)Equals
.neq(value)Not equals
.gt(value)Greater than
.gte(value)Greater than or equal
.lt(value)Less than
.lte(value)Less than or equal
.in([values])Value is in array
.exists()Field has a non-empty value

See Rules & Behavior for the full reference.