Skip to main content
A static property has one value. A dynamic value lets a property choose between values based on the current state of a variable. A button’s label, a text’s color, whether a control is disabled: any of these can change as the user moves through the flow, without you building separate screens. A dynamic value is a list of when <condition> -> value rules plus a fallback. The flow checks the rules in order and uses the first one that matches. If none match, it uses the fallback.

Static, interpolated, or conditional

A property value is one of three things:
  1. Static. One fixed value. This is the default.
  2. Interpolated (text only). A string with {{key}} tokens that are replaced with variable values. Interpolation does substitution only. See Variables.
  3. Conditional. An ordered set of rules, each with a condition and a result value, plus a fallback. This is what “dynamic value” means on this page.

Make a property dynamic

Many fields in the properties panel can become dynamic. The button’s Disabled toggle, text Color, a label, and similar properties show a control to switch from a single value to a rule-based value. When you open the dynamic value editor you get:
  • Driving variable. Pick the variable most of your rules compare against. New rules start pre-pointed at it, which saves repeating the choice.
  • Value stack. The ordered list of rules. Each rule has a Result value and a When this condition is true section. Drag rules to reorder them; order is priority, top to bottom.
  • Fallback value. The value used when no rule matches. This is the else of the conditional.
  • Add rule, a preset picker for common patterns, and Paste rule if you copied one from another property.
If you remove every rule, the property goes back to a plain static value (your fallback).

The condition builder

Each rule has one condition: a variable, an operator, and (for most operators) a value to compare against. The operators offered depend on the variable’s type.
Variable typeOperators offered
Stringequals, does not equal, contains, does not contain, starts with, ends with, is empty, is not empty
Numberequals, does not equal, greater than, less than, at least (>=), at most (<=)
Booleanis ON, is OFF
Listcontains, does not contain, is empty, is not empty
is empty and is not empty need no value. Boolean conditions are just is ON / is OFF, with no value to type. For anything more complex, open Advanced conditions. It lets you group rules with AND (“all conditions must match”) and OR (“any condition must match”). Most flows never need this.

First match wins

Rules are evaluated top to bottom and the first match wins. Put the most specific rule first and broader rules below it. Anything that matches no rule falls through to the fallback. A conditional value is stored like this:
{
  "type": "conditional",
  "cases": [
    {
      "when": { "op": "equals", "left": { "var": "user_type" }, "right": "premium" },
      "value": { "type": "static", "value": "#FFD700" }
    },
    {
      "when": { "op": "equals", "left": { "var": "user_type" }, "right": "basic" },
      "value": { "type": "static", "value": "#C0C0C0" }
    }
  ],
  "else": { "type": "static", "value": "#808080" }
}

You cannot use a ternary in interpolation

{{ }} interpolation does string substitution only. There is no ternary or conditional syntax inside {{ }}. To switch a value based on a condition, use a conditional property value (case/else against a condition) instead.
Swapping a value based on a condition is exactly what a conditional value is for:
Wrong (does nothing useful):
  {{ selected_plan == "yearly" ? "Continue with Yearly" : "Continue" }}

Right (a dynamic value on the label):
  when selected_plan equals "yearly" -> "Continue with Yearly"
  else                               -> "Continue"
{{ }} only ever substitutes a variable’s value. There is no logic inside the braces.

Example

A Continue button that disables until a plan is chosen. Make the button’s Disabled property dynamic, driven by selected_plan (a String variable that starts empty):
  • when selected_plan is empty -> true
  • else -> false
The button is disabled until a choice sets selected_plan, then it enables. A score readout that changes color at a threshold. Make a text’s Color dynamic, driven by a score Number variable:
  • when score at least 80 -> green
  • when score at least 50 -> amber
  • else -> red
Because the first matching rule wins, the 80 rule must come before the 50 rule. If you put 50 first, a score of 90 would still match 50 and never reach green.

Common mistakes

  • Reaching for a ternary. There is no ? : inside {{ }}. Use a conditional value with two cases.
  • Case order bugs. A broad rule above a specific one shadows it. Order rules from most specific to least specific.
  • Comparing a String with a number operator. Operators are filtered by the variable’s type, so a String variable never offers greater than. If you need numeric comparison, make the variable a Number.
  • Forgetting the fallback. If nothing matches and there is no fallback, the property has no value. Always set a sensible fallback.