MatchValue-based branching on a single discriminantGuide
Categories

Match

Basic Usage

{#match} branches on a single value. Name the value once, then list the cases it can take.

{#match status}
{is 'loading'}
Loading...
{is 'error'}
Error: {message}
{is 'success'}
{data}
{else}
Idle
{/match}

Each {is} case matches when the value loosely equals (==) one of its listed values. The first matching case wins, there is no fall-through. {else} is the fallback when nothing else matches.

Multiple Values per Case

A case can list several values separated by spaces. It matches when the discriminant equals any of them.

{#match plan}
{is 'free' 'trial'}
Limited features
{is 'pro' 'team' 'enterprise'}
All features
{else}
Unknown plan
{/match}

Expression Case Values

Case values are expressions evaluated against the data context, not just literals. A case can compare against a variable or a computed value.

{#match role}
{is adminRole}
Full access
{is 'guest'}
Read only
{is (resolveRole user)}
Custom
{/match}

A JavaScript expression that contains spaces needs parentheses so it reads as a single value, the same way Lisp-style arguments are tokenized by whitespace.

{#match key}
{is (mode + 'x')}
Matched
{/match}

Exact Matching

{is} compares with ==, so it coerces. null and undefined fall into the same case, as do the loosely equal falsy values 0, '', and false. {isExactly} compares with === instead, with no coercion. It takes the same values, expressions, and multiple-value lists as {is}, and is a case keyword the same way.

Strict matching is what separates a value you have not fetched from one you fetched and found empty.

{#match user}
{isExactly undefined}
Loading...
{isExactly null}
No user found
{else}
{user.name}
{/match}

With {is undefined} and {is null}, both cases match either value, so the first one wins for both. {isExactly} keeps them apart. The same is true of the falsy set: {is 0} also matches '' and false, while {isExactly 0} matches only the number.

Reactivity

The discriminant is reactive. When it changes, the block re-matches and swaps to the newly matching case, the same as {#if}.

{#match step}
{is 1}
<p>Choose a plan</p>
{is 2}
<p>Enter payment</p>
{is 3}
<p>Confirm</p>
{/match}

Match vs If

Reach for {#match} when you branch on the discrete values of one variable. It names that variable once instead of repeating it in every condition.

{#if status == 'loading'}
Loading...
{else if status == 'error'}
Error
{else if status == 'success'}
Done
{/if}

The same logic with {#match}:

{#match status}
{is 'loading'}
Loading...
{is 'error'}
Error
{is 'success'}
Done
{/match}

Stay with {#if} for unrelated conditions, ranges, or boolean tests, where there is no single value to branch on.

{#if temperature > 90}
Hot
{else if isWeekend}
Relax
{/if}

The is Keyword

Inside a {#match} block, is opens a case, so it shadows the is equality helper there. isExactly is gated the same way. To compare values directly in a case body, use == or the JavaScript form is(x, y).

{#match tab}
{is 'profile'}
{#if role == 'admin'}
Admin profile
{/if}
{/match}

Everywhere outside a match block, {is x y} and {isExactly x y} are the equality helpers, unchanged.

Previous
Conditionals
Next
Loops