Switch / Match
<switch> renders the first <match> whose
when is truthy, and nothing else. It is the multi-branch conditional, where
Show is the two-branch one.
<Switch> and <Match> are the same components.
<script>
let status = 'loading'
</script>
<select bind:value={status}>
<option value="loading">loading</option>
<option value="error">error</option>
<option value="success">success</option>
</select>
<switch>
<match when={status === 'loading'}><p class="badge grey">Loading...</p></match>
<match when={status === 'error'}><p class="badge red">Something went wrong</p></match>
<match when={status === 'success'}><p class="badge green">All done</p></match>
</switch>
<style>
.badge {
display: inline-block;
margin-top: 0.6rem;
padding: 0.2rem 0.6rem;
border-radius: var(--radius-sm);
font-size: 0.85rem;
}
.grey {
background: #6b72801f;
color: #6b7280;
}
.red {
background: #ef44441f;
color: #ef4444;
}
.green {
background: #22c55e1f;
color: #16a34a;
}
</style>Loading...
Conditions are checked top to bottom and the first hit wins, so put the specific ones before the general ones.
The Default Case
A <match> with no when matches anything. Put it last:
<script>
let count = 0
</script>
<button onclick="count++">Add one ({count})</button>
<switch>
<match when={count === 0}><p>Nothing here yet.</p></match>
<match when={count === 1}><p>One item.</p></match>
<match><p>{count} items.</p></match>
</switch>
<style>
button {
padding: 0.35rem 0.75rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-secondary);
color: var(--text-primary);
cursor: pointer;
}
</style>Nothing here yet.
<switch> also takes a fallback prop, which does the same job
in one line when the default is a scrap of markup rather than a branch:
<switch fallback="<p>Unknown status</p>">
<match when={status === 'loading'}><Spinner /></match>
<match when={status === 'error'}><ErrorMessage /></match>
</switch>
A default <match> wins over fallback if you write both.
Props
| Tag | Prop | Description |
|---|---|---|
<switch> |
fallback |
Literal markup to mount when no <match> matches. An expression in it
is a build error - put the dynamic case in a <match> arm.
|
<match> |
when |
The condition. Omit it entirely to make this the default branch. |
A matched arm has no wrapper element. It is inserted at a comment
anchor, so a <switch> inside a flex or grid parent puts the winning
arm's own content into that parent.
Alpha code often carries
[data-jaf-component="Switch"] { display: contents } for the
<div> that used to be there. Delete it - it matches nothing now.
A <match> body is the enclosing component's own markup: handlers and
their modifiers, class:, style:, bind: and
use: all resolve against it. ref: is refused in an arm, because
when the element appears is exactly what the compiler declines to promise.