> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getflowpilot.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic values

> Almost any property can switch its value based on a variable, using ordered conditional rules instead of a single fixed value.

A static property has one value. A **dynamic value** lets a property choose between values based on the current state of a [variable](/editor/variables). 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.

<Note>
  Conditional and dynamic values are an **Advanced mode** feature. [Simple mode](/editor/editing-modes) keeps any that exist (they render the same on device) but shows them as read-only and does not let you author new ones. The one curated exception is the [Required](/editor/block-controllers#required) toggle, which compiles to a conditional `disabled` value for you. Switch to Advanced to bind properties to variables and conditions.
</Note>

## 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](/editor/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 type | Operators offered                                                                                  |
| ------------- | -------------------------------------------------------------------------------------------------- |
| **String**    | equals, does not equal, contains, does not contain, starts with, ends with, is empty, is not empty |
| **Number**    | equals, does not equal, greater than, less than, at least (`>=`), at most (`<=`)                   |
| **Boolean**   | is ON, is OFF                                                                                      |
| **List**      | contains, 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:

```json theme={null}
{
  "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

<Warning>
  `{{ }}` 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.
</Warning>

Swapping a value based on a condition is exactly what a conditional value is for:

```text theme={null}
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.

## Related pages

* [Variables](/editor/variables)
* [The properties panel](/editor/properties)
* [Interactions and actions](/editor/interactions-and-actions)
* [Conditions and expressions (reference)](/reference/conditions-and-expressions)
