Patterns
Common compositions of the language's constructs.
Recipes for the compositions most documents end up needing. The element types are illustrative; a dialect defines its own. Each pattern is a prop value or a fragment of one, usable anywhere the construct is valid.
Conditional Section
Show a group of fields only when a checkbox is checked, with a
conditional resolving the slot. $matches is
omitted, so the condition tests for exactly true:
{
"type": "section",
"props": {
"children": {
"$if": { "$data": "/hasCompany" },
"$then": [
{
"type": "input",
"props": {
"label": { "$t": "form.companyName" },
"value": { "$field": "/company/name" }
}
},
{
"type": "input",
"props": {
"label": { "$t": "form.taxId" },
"value": { "$field": "/company/taxId" }
}
}
]
}
}
}Branching on a Field's Value
Choose between two values by testing a field against a JSON Schema with
$matches, falling back through $else:
{
"type": "input",
"props": {
"value": { "$field": "/company/name" },
"label": {
"$if": { "$data": "/customerType" },
"$matches": { "const": "company" },
"$then": { "$t": "form.companyName" },
"$else": { "$t": "form.organizationName" }
}
}
}Repeating List from Data
Render one element per item of an array with a map, reading
each item through the $item and $index
scoped arguments:
{
"type": "list",
"props": {
"children": {
"$map": { "$data": "/plans" },
"$each": {
"type": "list-item",
"props": {
"title": { "$arg": "$item/name" },
"subtitle": { "$arg": "$item/price" }
}
}
}
}
}Options from Data
A map also builds a plain array prop, such as a select's options, with nested positions reading the item through deep expressions:
{
"type": "select",
"props": {
"label": { "$t": "form.plan" },
"value": { "$field": "/plan" },
"items": {
"$map": { "$data": "/plans" },
"$each": {
"value": { "$arg": "$item/code" },
"label": { "$arg": "$item/name" }
}
}
}
}Complete Form Control
A control combining a translated label with a two-way field binding. The binding alone reads the field, writes user edits back, and tracks focus and validation:
{
"type": "input",
"props": {
"label": { "$t": "form.email" },
"value": { "$field": "/email" }
}
}An action on a bound element adds behavior alongside the automatic write-back, here resetting a dependent field when the value changes:
{
"type": "select",
"props": {
"label": { "$t": "form.country" },
"value": { "$field": "/country" },
"onChange": { "$action": "reset", "$args": ["/city"] }
}
}Writing the Callback Value
A callback injects its positional arguments as
$0, $1, …; passing $0 to the engine's
set handler writes the event value to a field:
{
"type": "slider",
"props": {
"label": { "$t": "form.budget" },
"onChange": { "$action": "set", "$args": ["/budget", { "$arg": "$0" }] }
}
}Dispatching a Sequence
An action prop also takes an array, dispatching each handler in order:
{
"type": "button",
"props": {
"label": { "$t": "form.submit" },
"onPress": [
{ "$action": "submit", "$args": [{ "$data": "" }] },
{ "$action": "reset", "$args": ["/draft"] }
]
}
}Switching on an Enum
Select a value per case of a discriminating field with switch/case:
{
"type": "text",
"props": {
"children": {
"$switch": { "$data": "/frequency" },
"$case": {
"daily": { "$t": "digest.daily" },
"weekly": { "$t": "digest.weekly" }
},
"$default": { "$t": "digest.monthly" }
}
}
}Localized Rich Text
A translation reference
interpolating data into the message and rendering its tags as elements,
with the tag content injected as $content:
{
"type": "text",
"props": {
"children": {
"$t": "signup.terms",
"$params": { "name": { "$data": "/name" } },
"$tags": {
"link": {
"type": "anchor",
"props": {
"href": "/terms",
"children": { "$arg": "$content" }
}
}
}
}
}
}