Skip to main content

The problem

Build-time if and for directives render once at compile time. Showing different branches or lists that change after user interaction needs either client-side templating or manual DOM create/destroy.

How Aero helps

With <script is:state>, structural directives reconcile against live state. The compiler still lowers templates to HTML, but the reactivity mount patches branches and list rows when bindings change. Build-time and runtime structural directives use the same syntax. The difference is the presence of a state script and reactivity: true.

Reactive conditionals

if, else-if, and else choose one branch based on a state expression:

Reactive switch

Match a state value against case branches, with default as fallback:

Keyed for loops

Reactive lists need a stable key so Aero can move or reuse DOM nodes instead of re-rendering the whole list:

In-place list mutation

Keyed for also reconciles when you mutate the same array, Set, or Map in place:
Immutable replacement (items = [...items, next]) and in-place mutation (items.push(next)) both notify the binding. Prefer immutable updates when you use view transitions or need a new reference for derived state.

Destructuring in for

The loop binding supports destructuring patterns:

Requirements

  • key must evaluate to a string or number per row.
  • Duplicate keys in one reconciliation pass throw at runtime.
  • The iterable may be an array, Set, Map, any object with [Symbol.iterator], or null / undefined (treated as empty).
  • Map rows iterate as [key, value] entry pairs — use destructuring in the loop binding.
Keyed reconciliation preserves focus and element state inside rows when items reorder. Pair with view transitions in client scripts for animated list updates.

Output fidelity

Reactive bindings anchor to authored markup instead of injecting wrapper elements:
  • Switchdata-aero-switch on the element with switch="{ … }".
  • Keyed fordata-aero-for on the parent container when the loop row is the only element child (e.g. <ul data-aero-for> with <li for> rows).
  • if chainsdata-aero-if on a parent wrapper when the chain is its only content; otherwise HTML comment boundaries (<!-- aero:if:N --><!-- /aero:if:N -->).
  • Text interpolationdata-aero-text on an element whose sole child is reactive text; mixed content uses comment boundaries. Prefer the explicit text="{ expr }" attribute when you need a marker on a specific element.
This keeps selectors like ul > li and :nth-child predictable in the live DOM.