Markup
The HTML that a component outputs is declared within a @render
block. There can only be one @render block per component. Each @render block must contain a single root element:
export default function Component() {
@render {
<p>Hello!</p>
}
}
Dynamic content
You can include dynamic content in text and attributes using braces:
export default function Component() {
const className = "extravagant"
const name = "Torpor"
@render {
<p class={className}>
Hello, {name}!
</p>
}
}
Use this shortcut syntax to set the value of an attribute to a value of the same name:
export default function Component() {
const id = "main"
@render {
<p {id}>
Hello, {name}!
</p>
}
}
If statements
Use an @if
statement to show certain markup when a condition is met:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
<button onclick={() => $state.counter--}>Decrement</button>
{$state.counter}
<button onclick={() => $state.counter++}>Increment</button>
@if ($state.counter < 0) {
<p>The count is negative.</p>
} else if ($state.counter > 0) {
<p>The count is positive.</p>
} else {
<p>The count is zero.</p>
}
</div>
}
}
For loops
Use a @for
loop to show multiple elements:
export default function Component() {
let $state = $watch({
stock: [
{ code: "W1", name: "Widgets", quantity: 5 }
{ code: "B2", name: "Boxes", quantity: 12 }
{ code: "D3", name: "Doodads", quantity: 3 }
]
})
@render {
<div>
<button onclick={() => $state.stock.sort((a, b) => a - b)}>
Sort by quantity
</button>
@for (let $item of $state.stock) {
@key $item.code
<p>{$item.name}: {$item.quantity}</p>
}
</div>
}
}
Note the use of the (optional) @key statement to store a unique value for each loop item. If set, when the list is updated (e.g. when sorting), the @key value will be used to recycle the DOM elements rather than destroying and recreating each one.
Switch statements
Use a @switch
statement to show one of many options:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
{$state.counter}
<button onclick={() => $state.counter++}>Increment</button>
@switch ($state.counter) {
case 0: {
<p>It's zero.</p>
}
case 1: {
<p>It's one.</p>
}
case 2: {
<p>It's two.</p>
}
case 3: {
<p>It's three.</p>
}
case 4: {
<p>It's four.</p>
}
default: {
<p>It's bigger than four.</p>
}
}
</div>
}
}
Note that the switch statement differs from the JavaScript switch statement in that each case statement must be surrounded by braces and no fallthroughs are allowed (meaning that the break
statement can be omitted).
Await statements
Use an @await
statement to show the result of an asynchronous function:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
</div>
}
}
Replace statements
Use a @replace
statement to re-render markup when a value is changed:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
</div>
}
}
This can be used to re-run component $mount statements and to re-play transition animations.
@const, @console and @debugger
The @const
keyword can be used to declare a constant value within markup, the @console
keyword can be used to log information within markup, and the @debugger
keyword can be used to break code execution during markup rendering:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
</div>
}
}
Function declarations
Use the @function
statement to declare a function within markup. This can be useful for keeping logic close together, e.g. for moving a large onclick handler out of an onclick attribute, but still keeping it next to the button it is called from:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
</div>
}
}
HTML rendering
Use a @html
statement to render plain HTML within markup, e.g. from a database:
export default function Component() {
let $state = $watch({ counter: 0 })
@render {
<div>
</div>
}
}
Note that when rendering HTML you should ensure that it is properly escaped to prevent script injection and other attacks.