Dynamic switching
Studio writes this format for you. There is no dedicated panel for
$switchyet — add it in Code mode and the canvas renders whichever case is active.
A
$switch
node swaps what renders in one spot based on a state value: the node binds
$switch
to a
reference
, and
cases
maps each possible value to what should render. When the state changes, the old case is torn down and the new one renders in its place — view switching, wizard steps, or a client-side router in pure JSON.
{
"tagName": "main",
"children": [
{
"$switch": { "$ref": "#/state/currentRoute" },
"cases": {
"home": { "$ref": "./views/home.json" },
"about": { "$ref": "./views/about.json" },
"profile": { "$ref": "./views/profile.json" }
}
}
]
}
External cases
A case value that is a
$ref
to a
.json
file loads that
document
on demand — a case is fetched only when its key first becomes active, so unvisited views cost nothing up front. Each external case is an independent component with its own
state
scope.
Inline cases
A case value may also be an inline element definition. Inline cases render in the surrounding document's scope, so they can bind its state directly:
{
"$switch": { "$ref": "#/state/status" },
"cases": {
"loading": { "tagName": "p", "textContent": "Loading…" },
"error": { "tagName": "p", "textContent": "undefined" },
"success": { "$ref": "./views/results.json" }
}
}
Driving the switch
The selector is ordinary state, so anything that writes state switches the view — an event handler, an expression , or a data source:
{
"state": { "currentRoute": "home" },
"children": [
{
"tagName": "button",
"textContent": "About",
"onclick": {
"$expression": {
"operator": "=",
"target": { "$ref": "#/state/currentRoute" },
"value": "about"
}
}
}
]
}
How it works
The runtime renders the
$switch
node as a container element (its
tagName
, or
div
when none is given) and watches the bound reference inside a reactive effect. On every change it clears the container and renders the matching case: inline cases render immediately with the current scope; external cases are fetched, their scope is built, and the result is appended — with stale responses discarded if the key changed again mid-load. A key with no matching case renders nothing.
Rules
$switchmust be a$ref— typically#/state/...; a literal value is meaningless and does not render.Case keys are matched against the resolved value as strings; there is no default case — an unmatched value renders an empty container.
External cases have isolated scope; to share data with a case, make it an inline element, or lift shared state to
window#/globals.Switching fully tears down the outgoing case — its DOM and reactive bindings are disposed, and per-component state re-initializes on the next visit.
For URL-driven pages prefer file-based routing ;
$switchis for switching within a page.
Related
References — the
$refschemes$switchbindsState — declaring the selector value
Props and scope — why external cases are isolated
Routing — URL-based page selection for sites
Code editing — the Studio surface for authoring
$switch