Skip to content

Conditional visibility

Three tokens decide whether a field renders:

Token Purpose
x-lt-showIf Show the field when a condition over the escalation context or the live form holds
x-lt-hide-if-empty Suppress the field when its own value is empty
x-lt-hidden Never render the field; its value still passes through

Apply x-lt-showIf to any property:

"x-lt-showIf": "domain.path"

The value at domain.path is tested for truthiness. A truthy value shows the field; an absent, null, false or empty-string value hides it. Prefix ! to invert: show when the value is absent or falsy.

Compare the resolved value’s string form with a literal:

"x-lt-showIf": "resolver.disposition=rework"
"x-lt-showIf": "resolver.disposition!=rework"

The expected value is the raw remainder after the operator, trimmed and unquoted. Numbers and booleans compare through their string form (metadata.count=3, metadata.live=true). An absent value compares as the empty string, so =X is false and !=X is true when the path is missing. resolver. conditions react live as the person edits, so one verdict form can carry a different set of fields for each disposition.

Pass an array to require every condition. The field shows only when all hold:

"x-lt-showIf": ["input.action=report-issue", "!input.restarted"]

Each entry uses the same grammar as a single condition. Validation skips a hidden field exactly as it does with one condition.

Domain Resolves against
metadata The row’s metadata
payload The escalation context payload (escalation_payload)
envelope The input envelope the workflow sent
escalation Top-level escalation row fields (role, status, priority, and so on)
resolver The resolver payload, live: reacts as the person edits the form
input The same live form values under the invoke form’s name (see Invoke forms)
roster Each roster field’s counts, live: roster.orders.outstanding=0 shows a field once every member is accounted for

Conditions on metadata, payload, envelope and escalation read the stored row. Conditions on resolver are live: the field appears or disappears as the person edits a sibling field.

A queue receives regular work items and an occasional shutdown signal. The payload carries shutdown_signal to tell them apart:

{
"title": "Worker station",
"properties": {
"action_taken": {
"type": "string",
"enum": ["completed", "deferred", "escalated"],
"description": "Outcome for this work item",
"x-lt-showIf": "!payload.shutdown_signal"
},
"notes": {
"type": "string",
"format": "textarea",
"x-lt-showIf": "!payload.shutdown_signal"
},
"shutdown_ack": {
"type": "boolean",
"title": "Acknowledge shutdown",
"description": "Confirm you are stopping work and clearing the station",
"x-lt-showIf": "payload.shutdown_signal"
}
}
}

rejection_reason hides while approved is checked. Because the condition targets resolver.approved, the field appears the moment the person unchecks the box. required lists rejection_reason, and the required check applies only while the field shows:

{
"title": "Quality review",
"x-lt-order": ["approved", "rejection_reason", "notes"],
"required": ["rejection_reason"],
"properties": {
"approved": {
"type": "boolean",
"description": "Approve this submission"
},
"rejection_reason": {
"type": "string",
"format": "textarea",
"description": "Explain why this submission needs rework",
"x-lt-showIf": "!resolver.approved"
},
"notes": {
"type": "string",
"format": "textarea",
"description": "Reviewer notes"
}
}
}

In the workflow, guard the optional fields before reading them:

const decision = await conditional<{
approved: boolean;
rejection_reason?: string;
notes?: string;
}>(signalId, { role: 'quality-reviewer' /* ... */ });
if (!decision.approved) {
await sendForRework({ reason: decision.rejection_reason, notes: decision.notes });
} else {
await advanceOrder();
}

A hidden field stays in form state. Its value submits only if it was filled before the field hid. Required validation skips fields hidden at submit time.

A field with "x-lt-hide-if-empty": true is suppressed when its value is null, an empty string, false or 0. It suits readOnly facts present on only some escalations:

{
"properties": {
"gift_message": {
"type": "string",
"readOnly": true,
"x-lt-hide-if-empty": true,
"description": "Gift message from the order"
},
"notes": {
"type": "string",
"readOnly": true,
"x-lt-hide-if-empty": true,
"description": "Additional processing notes"
}
}
}

x-lt-hide-if-empty reads the field’s own current value. x-lt-showIf reads a path in the escalation context or the live form.

A field with "x-lt-hidden": true never renders. Use it for a value the form carries that a workflow or API caller sets, such as a discriminant. The value passes through to the resolver payload unchanged, and where the schema is enforced it is checked against the field’s type and enum. A hidden field is never required, even when required lists it.

"type": {
"type": "string",
"enum": ["release", "reset", "cancel"],
"x-lt-hidden": true
}