Skip to content

States

States are named boolean expressions over the live form data. Declare them once in formConfig.states, then reference the names from include / exclude rules, per-state property overrides, and selectors.

const formConfig = {
states: {
hasDiscount: '$form.hasDiscountCode === true',
isAdult: '$form.driverAge >= 18',
},
};

Expressions are JavaScript-like. The engine exposes:

  • $form — the current form data tree.
  • Standard operators: &&, ||, !, ===, !==, <, >, <=, >=, +, -, *, /, ?:.
  • Optional chaining: $form.user?.name.

Expressions can reference any path in the form data.

  • In include / exclude rules: gate widgets.
  • In per-state property overrides on shortcuts: change props when active.
  • In gui.selectors.state(...) chains: scope a selector to one state.

Two properties on every shortcut control whether a widget renders:

PropertyShape
include{ in: ['stateName', ...] } — render when any named state is active. Or { when: '<expr>' } — render only when the expression is truthy.
exclude{ from: ['stateName', ...] } — render unless any of the named states are active. Or { when: '<expr>' } — render unless the expression is truthy.

Note the field names — include uses in, exclude uses from. Both also accept when for inline expressions that don’t need a name.

When to use each

  • include with in — the condition has a name and is used in multiple places (gating, prop overrides, selectors).
  • include with when — a one-off condition, expressed inline, not worth declaring a state for.
  • exclude — when “hide-when X” reads more naturally than “show-unless X”.

Putting it together — a support-ticket form

Section titled “Putting it together — a support-ticket form”

The demo below shows the three gating mechanisms working side by side:

  • include: { in: ['isBug'] } on the Steps to reproduce textarea — render only when the named state is active.
  • include: { in: ['isBug', 'isBilling'] } on the Priority radiogroup — render when any of the listed states is active (OR semantics).
  • exclude: { from: ['isBilling'] } on the Marketing opt-in checkbox — render unless the named state is active.
  • include: { when: '$form.subscribeNewsletter === true' } on the Newsletter frequency radiogroup — an inline reactive expression for a one-off condition where naming a state would be overkill.
import { gui } from '@golemui/gui-shared';
const formDef = [
gui.inputs.radiogroup('issueType', {
label: 'What can we help you with?',
options: [
{ value: 'bug', label: 'Bug report' },
{ value: 'billing', label: 'Billing question' },
{ value: 'feature', label: 'Feature request' },
{ value: 'other', label: 'Other' },
],
direction: 'row',
}),
gui.inputs.textarea('description', {
label: 'Description',
placeholder: 'Tell us what happened…',
}),
// include — only render when isBug is active.
gui.inputs.textarea('reproSteps', {
label: 'Steps to reproduce',
placeholder: '1. Go to …\n2. Click …\n3. Notice …',
include: { in: ['isBug'] },
}),
// include with multiple states — render when ANY is active.
gui.inputs.radiogroup('priority', {
label: 'Priority',
options: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
],
direction: 'row',
include: { in: ['isBug', 'isBilling'] },
}),
// exclude — render unless isBilling is active.
gui.inputs.checkbox('marketingOk', {
label: 'You may share my email with our partners.',
exclude: { from: ['isBilling'] },
}),
// inline `when` — no named state needed for a one-off condition.
gui.inputs.booleanInput('subscribeNewsletter', {
label: 'Subscribe to the product newsletter',
}),
gui.inputs.radiogroup('newsletterFrequency', {
label: 'How often?',
options: [
{ value: 'weekly', label: 'Weekly' },
{ value: 'monthly', label: 'Monthly' },
],
direction: 'row',
include: { when: '$form.subscribeNewsletter === true' },
}),
gui.actions.button({ label: 'Submit ticket', actionType: 'submit' }),
];
const formConfig = {
states: {
isBug: '$form.issueType === "bug"',
isBilling: '$form.issueType === "billing"',
},
};

Try it: switch the issue type and watch the Steps to reproduce appear/disappear (named-state include), the Priority show for both Bug and Billing (multi-state include), and the marketing opt-in disappear when you pick Billing (named-state exclude). Then toggle the newsletter switch — the frequency radio uses an inline when expression with no named state at all.

  • Features / States — gating, per-state property overrides, composing states.
  • Runtime Functions — when a one-off prop should react to data per-render rather than via a named state.