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>
output

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>
output

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:

source
<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.