Conditional Logic
Forma uses FEEL expressions to control dynamic field behavior. Three properties control when fields are visible, required, or editable.
Properties
| Property | Description | Default |
|---|---|---|
visibleWhen | Show field when expression is true | Always visible |
requiredWhen | Require field when expression is true | Uses schema required |
enabledWhen | Allow editing when expression is true | Always enabled |
readonlyWhen | Make field read-only when expression is true | Always editable |
visibleWhen
Control when a field is displayed:
{
"dependentField": {
"label": "Dependent Field",
"visibleWhen": "triggerField = true"
}
}
Examples
Show based on checkbox:
{
"visibleWhen": "hasInsurance = true"
}
Show based on selection:
{
"visibleWhen": "country = \"US\""
}
Show based on number:
{
"visibleWhen": "age >= 18"
}
Show based on multiple conditions:
{
"visibleWhen": "hasInsurance = true and insuranceType = \"health\""
}
Hidden Field Behavior
- Hidden fields are not validated
- Hidden fields retain their values (not cleared)
- Hidden fields are excluded from submission if not visible
requiredWhen
Make a field conditionally required:
{
"insuranceNumber": {
"label": "Insurance Number",
"visibleWhen": "hasInsurance = true",
"requiredWhen": "hasInsurance = true"
}
}
Priority
requiredWhenoverrides the schema'srequiredarray- If both schema
requiredandrequiredWhenare set,requiredWhentakes precedence
Examples
Required based on selection:
{
"requiredWhen": "paymentMethod = \"credit_card\""
}
Required based on checkbox:
{
"requiredWhen": "needsShipping = true"
}
enabledWhen
Control when a field can be edited:
{
"approvedBy": {
"label": "Approved By",
"enabledWhen": "status = \"pending\""
}
}
Disabled fields:
- Are visible but grayed out
- Cannot be edited by the user
- Retain their existing value
Examples
Disable after submission:
{
"enabledWhen": "submissionStatus != \"submitted\""
}
Enable only for specific users:
{
"enabledWhen": "userRole = \"admin\""
}
readonlyWhen
Make a field conditionally read-only:
{
"invoiceNumber": {
"label": "Invoice Number",
"readonlyWhen": "status = \"approved\""
}
}
Readonly fields differ from disabled fields (enabledWhen: false):
- Readonly: Visible and focusable, values are submitted, but the field cannot be edited
- Disabled: Field appears greyed out and cannot be interacted with
Examples
Read-only after approval:
{
"readonlyWhen": "approvalStatus = \"approved\""
}
Read-only for non-admins:
{
"readonlyWhen": "userRole != \"admin\""
}
FEEL Expression Syntax
Comparison Operators
| Operator | Description | Example |
|---|---|---|
= | Equal | status = "active" |
!= | Not equal | status != "archived" |
> | Greater than | age > 18 |
>= | Greater or equal | age >= 21 |
< | Less than | price < 100 |
<= | Less or equal | price <= 50 |
Logical Operators
| Operator | Description | Example |
|---|---|---|
and | Both conditions true | age >= 18 and hasLicense = true |
or | Either condition true | status = "active" or status = "pending" |
not | Negation | not(isBlocked) |
String Values
Strings must be quoted with escaped quotes:
{
"visibleWhen": "country = \"US\""
}
Null Checks
{
"visibleWhen": "email != null"
}
Referencing Other Fields
Reference fields directly by name:
{
"visibleWhen": "firstName != null and lastName != null"
}
Referencing Computed Values
Use the computed. prefix:
{
"visibleWhen": "computed.total > 1000"
}
Common Patterns
Show Additional Fields
{
"otherReason": {
"label": "Please specify",
"visibleWhen": "reason = \"other\""
}
}
Conditional Sections
Group related fields with the same condition:
{
"companyName": {
"label": "Company Name",
"visibleWhen": "customerType = \"business\""
},
"taxId": {
"label": "Tax ID",
"visibleWhen": "customerType = \"business\""
}
}
Progressive Disclosure
Reveal fields as users complete previous ones:
{
"step2Field": {
"visibleWhen": "step1Field != null"
},
"step3Field": {
"visibleWhen": "step2Field != null"
}
}
Mutual Exclusion
Show one field OR another:
{
"phoneNumber": {
"visibleWhen": "contactMethod = \"phone\""
},
"emailAddress": {
"visibleWhen": "contactMethod = \"email\""
}
}