LogicLast updated on
Last updated on
Conditional visibility, validation rules, and expressions
Logic adds dynamic behavior to forms. Instead of static structures, you can define rules that control when fields appear, when they're required, and what values are valid.
Logic is defined at design time but evaluated at runtime, when the form is filled with data.
Where Logic Applies
Logic expressions can control:
visible— whether a field or annex appearsrequired— whether a field or annex must be filledreadonly— whether a field can be edited
const form = open.form()
.name("application")
.fields({
hasVehicle: { type: "boolean", label: "Do you have a vehicle?" },
vehicleMake: {
type: "text",
label: "Vehicle Make",
visible: "fields.hasVehicle.value",
required: "fields.hasVehicle.value",
},
})
.build()When hasVehicle is true, vehicleMake becomes visible and required. When false, it's hidden.
Expression Syntax
Expressions are strings that reference field values and use logical operators:
// Access field values
visible: "fields.age.value >= 18"
// Logical operators: and, or, not
visible: "fields.isOwner.value or fields.isAgent.value"
required: "fields.age.value >= 18 and fields.hasLicense.value"
visible: "not fields.isMinor.value"
// Comparison: ==, !=, >, >=, <, <=
visible: "fields.country.value == 'USA'"Named Expressions
When the same logic appears in multiple places, define it once in the .logic section and reference it by name:
const form = open.form()
.name("application")
.fields({
age: { type: "number" },
drivingLicense: { type: "text", visible: "isAdult", required: "isAdult" },
parentConsent: { type: "boolean", visible: "not isAdult", required: "not isAdult" },
})
.logic({
isAdult: { type: "boolean", value: "fields.age.value >= 18" },
})
.build()Named expressions reduce duplication and create a single source of truth for business rules.
Logic in Annexes
Annexes support the same logic properties as fields:
const form = open.form()
.name("lease-application")
.fields({
hasPets: { type: "boolean", label: "Do you have pets?" },
})
.annexes({
petPhoto: open.annex()
.title("Pet Photo")
.visible("fields.hasPets.value")
.required("fields.hasPets.value"),
})
.build()Design Time vs Runtime
Logic expressions are defined at design time but evaluated at runtime. The form definition doesn't change—the same logic produces different results based on the data:
const filled1 = form.fill({ fields: { age: 15 } })
// drivingLicense is hidden, parentConsent is visible
const filled2 = form.fill({ fields: { age: 21 } })
// drivingLicense is visible, parentConsent is hidden