Conditional fields
A static dialog asks the user the same questions every time. A conditional dialog asks the right ones depending on what the user has already typed — show Bank details only when Payment method is bank_transfer, require Reason only when Status is cancelled, lock Account number in edit mode but allow editing in add mode.
Three flags on a column (or per-dialog override on a field) handle this:
| Flag | What it gates |
|---|---|
visible_when | Whether the field shows at all. Hidden fields don't bind values at save. |
required_when | Whether a value is mandatory. |
disabled_when | Whether the field is read-only. |
Each is a list of FieldCondition predicates — AND semantics, so every predicate must match for the rule to fire.
The FieldCondition shape
{ field = "STATUS", value = "CANCELLED" }
# or with a list — any matching value triggers the rule
{ field = "PAYMENT_METHOD", value = ["bank_transfer", "sepa"] }
| Property | What it does |
|---|---|
field | The other dialog field whose live value gates this rule. Referenced by its column name (case-insensitive). |
value | The expected value, or a list of values (any one matches). |
Multiple conditions in the list = AND. To OR conditions, declare two separate fields with the same conditional rule (or use a single condition with a list of values).
Where to set them
Two layers carry the same flags:
| Layer | When |
|---|---|
| Column hint (Columns tab) | The rule applies to every dialog that surfaces this column. The right default — most fields behave the same across dialogs. |
| Per-dialog field (Inspector → Conditional rules) | The rule applies only to this specific dialog. Use when one dialog needs different behaviour from the column-wide default. |
The runtime evaluates the per-field override first; if blank, it falls back to the column-hint setting.
The Inspector's Conditional rules section
When a field is selected in the Dialog builder's canvas, the Inspector's Conditional rules section lets you add predicates for any of the three flags.
| Section | What it does |
|---|---|
| visible_when | Show the field only when every predicate matches. Empty = fall back to the static hidden flag. |
| required_when | Require the field only when every predicate matches. Empty = required decides. |
| disabled_when | Lock the field only when every predicate matches. Empty = disabled decides. |
The runtime re-evaluates the rules on every form change — type in PAYMENT_METHOD, the dependent fields appear / disappear / lock without a round-trip.
Worked examples
Show fields conditionally
A Payment dialog with these columns:
PAYMENT_METHOD— ENUM dropdown (cash,bank_transfer,sepa,card).IBAN,BIC— only relevant forbank_transfer/sepa.CARD_LAST4— only relevant forcard.
The rules:
| Column | visible_when |
|---|---|
IBAN | field=PAYMENT_METHOD, value=[bank_transfer, sepa] |
BIC | field=PAYMENT_METHOD, value=[bank_transfer, sepa] |
CARD_LAST4 | field=PAYMENT_METHOD, value=card |
The user picks cash — IBAN / BIC / CARD_LAST4 all disappear. Switches to bank_transfer — IBAN and BIC appear, CARD_LAST4 stays hidden.
Require a reason on cancel
A Subscription dialog where CANCELLATION_REASON should only be required when STATUS = CANCELLED:
| Column | required_when |
|---|---|
CANCELLATION_REASON | field=STATUS, value=CANCELLED |
The field is always visible (no visible_when), always editable (no disabled_when), but the Save button refuses to submit until the field has a value if STATUS is CANCELLED. For any other status, an empty CANCELLATION_REASON saves fine.
Lock fields in edit mode for certain rows
A Customer dialog where the TAX_ID should be editable only when the row is being created (not edited):
| Column | disabled_when |
|---|---|
TAX_ID | (rule based on some marker that distinguishes add from edit — typically a row-level flag like IS_FROZEN) |
When the row's IS_FROZEN = Y, the TAX_ID field is read-only. Otherwise editable. The form is the same; the behaviour adapts to the row.
For a strict "lock when editing, allow when adding" without a row marker, use the per-tab hide_on_add / hide_on_edit flags or the per-field column-hint disabled (which locks everywhere).
Multi-condition AND
A Invoice dialog where EARLY_PAYMENT_DISCOUNT should be required only when both STATUS = OPEN AND AMOUNT_DUE > 1000:
The first condition is straightforward (STATUS = OPEN). The second isn't — FieldCondition checks equality, not comparison. For numeric thresholds use a normalised flag column (e.g. HIGH_VALUE = Y computed in the read query) and condition on it.
Sometimes the cleanest move is a dictionary rule with a default value that the user can override — let the form compute the discount and treat the field as informational rather than gating its save.
Visible vs hidden — what happens at save
A field hidden by visible_when is excluded from the save payload. The dialog Save sends only the values of currently-visible fields. The hidden field's database column either:
- Keeps its existing value (UPDATE — the missing field is omitted from the SET clause).
- Defaults to NULL or its DB default (INSERT — the missing field is omitted from the INSERT column list).
This is the intent of conditional visibility — a field that isn't relevant to the user's choice shouldn't accidentally overwrite the database with stale or default data.
For genuinely hidden-but-required fields (e.g. a :LOGIN_USER bound at save time), use parameter binding on the _post / _put query, not a dialog field.
Validation order
When the user clicks Save, the dialog checks fields in this order:
- Visible fields with
required = true(orrequired_whenmatching) must have a value. - Each field's dictionary rule fires (BOOLEAN, ENUM, LOOKUP, format).
- The Save dispatch fires the action chain.
A failing required check shows an inline error on the field, blocks the save, doesn't fire the action chain.
Common pitfalls
| Mistake | Symptom | Fix |
|---|---|---|
visible_when references a field not on any dialog tab. | The dependent field never appears (the source field's value is undefined, no condition matches). | Add the source field to the dialog, or change the condition. |
visible_when on a key field. | The user adds a row with no key — the INSERT fails. | Key fields should never be conditionally hidden. Lock them, don't hide. |
required_when matches but visible_when doesn't. | The field is required AND hidden — the user can't fill it but the save refuses. | Sync the two conditions, or drop the required_when. |
| Value list with a typo. | The rule never matches. | Verify the enum values match exactly (case-sensitive). |
| Condition references the field itself. | Infinite loop guard kicks in; the rule is ignored. | Conditions reference other fields, never self. |
What's next
- Actions and lifecycle — fire actions when the form loads, saves or is cancelled.
- Dialog builder — the Visual Builder where you set these rules per field.
- Columns — set the same rules at the column level for screen-wide defaults.