Guide 10 · Developer docs

Forms and data capture

Building forms with the Forms module: how a form is put together and placed on a page, validating and branching, presenting it, where submissions are stored, and what happens after one arrives, from jobs and records to CRMs and payments.

L1–L2
Unit 07 · Reference

js-forms-conditionals.js reference

The platform's script that applies a form's conditional logic in the browser: when it starts, the data the layout must print, the markup it looks for, when it re-evaluates, and what it does and does not undo.

Who this is for. The front-end developer building or checking a form's conditional fields in the browser. What the rules mean is on Conditional logic; this page is the script's contract.

The file and when it starts

Served by every site at /assets/forms/js-forms-conditionals.js. It works on every .coredna-js-form container, on both form models: a page-per-step layout wraps its form in the container for this script's sake (the wiring).

It starts only on the page's DOMContentLoaded event. Load it with a plain or a defer script tag in the page, not with async or from another script, so it starts before that event. (js-forms.js starts either way; this one does not.)

The data the layout prints

For each container, the script reads the form id from input[name="_formId"] and the rules from window['formConditionals' + formId], which the layout prints from the form's active revision (the snippet).

  • No variable: "Conditionals not found for form ID: n" in the console, and the form keeps every field visible. Print an empty list for a form without rules.
  • Every container needs its _formId input, so the script can set this container up, and the ones after it on the page.

The variable is a list of conditionals, each with conditions (all must match) and actions. Each condition and action has an entity and settings with field, state and, where it applies, value:

Entityfieldstate
Forms\Entities\ConditionValueElement idfilled, empty, checked, unchecked
Forms\Entities\ConditionStringElement idequal, not_equal, contains, not_contains
Forms\Entities\ConditionNumericElement idless, greater, less_equal, greater_equal
Forms\Entities\ConditionDateElement idequal, not_equal, before_date, after_date
Forms\Entities\ConditionMatchElement idregex, not_regex
Forms\Entities\ActionFieldVisibilityElement idshow, hide
Forms\Entities\ActionGroupVisibilityGroup's element idshow, hide
Forms\Entities\ActionStepVisibilityThe step's nameshow, hide
Forms\Entities\ActionRequirementsElement idrequired, not_required
Forms\Entities\ActionUpdateElement idNone; value is the new value
Forms\Entities\ActionClassElement idadd_class, remove_class; value holds the classes, separated by spaces

The markup it looks for

TargetFound byWhat changes
A field in a condition[data-id="element id"]; every input with that id, so a radio group or checkbox list is read as oneNothing; its value is read
A field to show or hideThe closest .base-element-block, or .static-element-block, around [data-id]Its display
A groupfieldset.element-group-block[data-id="…"]Its display
A step.form-step[data-step-name="…"]Its display, and data-skipped="true" while hidden, which js-forms.js steps over
A static element's text, for Update.element-text inside itIts text
Classes, for ClassThe .base-element-block.input-element-block around the field, or the static blockIts classes

The platform's own form markup carries all of these. A layout that prints its own fields has to keep data-id, the block classes and data-step-name; every element needs an id.

When it evaluates

  • Once at the start. A conditional with no conditions is applied then, once, as the starting state. A field or group that some rule shows starts hidden.
  • On every input event of a field that a condition reads. Text, number, date, datetime and time inputs wait one second after the last keystroke; selects, checkboxes, radio buttons, email inputs and textareas are evaluated at once.
  • Not when a script sets a value. Setting field.value or field.checked fires no input event, so a prefill or a helper that fills a field a rule depends on must fire one afterwards: field.dispatchEvent(new Event('input', { bubbles: true })).

When rules conflict about a field or group, hide wins, whatever their order. Keep a form's rules from conflicting, so the server reaches the same result; see Conditional requirements and validation.

What an action does, and what is undone

ActionWhen its conditions matchWhen they stop matching
Field, Group or Step Visibility, hideHidden; every input inside is cleared (unticked, or emptied) and loses requiredShown again with required restored; the cleared answers are not
RequirementsAdds or removes requiredUndone
ClassAdds or removes the classesUndone
UpdateSets the field's value, or a static element's textNot undone: the value stays, and is submitted like a typed answer

Because a hidden field is emptied, a visitor who opens a branch, types, and closes it again loses what they typed there; that is deliberate, so a hidden answer is never sent.

Three points to keep in mind

  • Update is one-way. It does not set the value back when the condition stops matching: pair it with a second conditional for the opposite case.
  • Write patterns without slashes or flags (Conditional logic).
  • The server applies requirements on its own. A required field on a hidden step is still required there (Three levels).
Go deeper

Was this page helpful?

Your answer goes to the docs team.