Corteksa
GuidesOther

CONDITIONAL VISIBILITY

CONDITIONAL VISIBILITY

Show or hide a single field in the record form/detail based on a condition evaluated on another field of the same object. Pure presentation behavior — no new field type, no physical column, no data mutation. Gated behind CONDITIONAL_FIELD_VISIBILITY_ENABLED; when off, every field is always visible and required/validation behave exactly as before.

Where it lives

The rule is stored on the target field's existing options JSON as conditional_visibility. It reuses the conditional_requirement operator engine (ValidationEngineService) and the shared operand-resolution util — there is no new evaluation engine.

"conditional_visibility": {
  "enabled": true,
  "action": "show",            // "show" ⇒ visible when met; "hide" ⇒ hidden when met
  "logic": "AND",              // AND | OR fold across conditions (default AND)
  "conditions": [
    { "trigger_field_slug": "customer_type", "operator": "equals", "values": ["business"] }
  ],
  "clear_on_hide": false       // default: retain the hidden value; true ⇒ null it on write
}

A single-condition rule may use the flat shorthand (trigger_field_slug/operator/values); config-time validation folds it into conditions[] and canonicalises operand values to the runtime-comparable form.

Operators (same enum as conditional_requirement): equals | not_equals | in | not_in | is_empty | is_not_empty. Select-family triggers compare by canonical option value/id, never label.

Correctness invariants (server-enforced)

RuleBehavior
Hidden ⇒ not required (FR-3520)A field the server computes as hidden has its required check and its conditional_requirement skipped, so a hidden required field can never dead-end a save. Enforced in both DynamicValidationService (static required) and ValidationEngineService (required-if).
Hidden value (FR-3521)Retained un-validated by default; clear_on_hide: true nulls it on write.
Server is source of truth (FR-3522)On every write the server re-evaluates each rule from submitted data; the client's hidden state is a hint only.
Cycle / self-reference (FR-3530)Rejected at configure time: 422 VISIBILITY_SELF_REFERENCE, 422 VISIBILITY_CYCLE.
Dangling / deactivated trigger (FR-3531)Rule inert ⇒ field visible (fail-open); never crashes.
Fail-open everywhereAny eval error, missing trigger, or empty/disabled rule resolves to visible + validated normally — hiding is what creates the dangerous hidden-required dead-end, so we never hide on a rule we could not evaluate.

Scope

Visibility is a form/detail concern. List/table/kanban/export column layout and the field's physical column + stored value are unaffected — a hidden field still has its column, still holds its value, still exports it.

Hiding is not a security control. A hidden field is still returned by the API, exported, rendered in documents, and writable by workflow/AI. Restricting who can read a field is field-level permission — a separate, not-yet-built control.

Code map

ConcernFile
Rule shapeobject/shared/interfaces/conditional-visibility.interface.ts
Shared operator + operand resolutionobject/shared/utils/condition-evaluator.util.ts
isFieldHidden evaluatorobject/shared/utils/conditional-visibility.util.ts
Feature flagobject/fields/services/visibility-feature.ts
Config-time guard (cycle/self-ref/trigger)object/fields/services/field/utils/validate-conditional-visibility.ts
Write-path skip-required + clear/retainobject/fields/services/validation/dynamic-validation.service.ts
Required-if skip when hiddenobject/fields/services/validation/validation-engine.service.ts
Config wiringfield-create.service.ts / field-update.service.ts

On this page