Template syntax
Templates are HTML with three additions: text interpolation, attribute bindings, and
event handlers. Structural directives (tn-if, tn-for, …)
are covered separately.
Text interpolation
Use {{ }} to render a reactive value into text. Remember that signals are read by
calling them:
<script lang="ts">
import { createSignal } from 'tannijs';
const [name, setName] = createSignal('World');
</script>
<template>
<p>Hello, {{ name() }}!</p>
</template>
Interpolations can be mixed with static text and contain any JavaScript expression. When a signal used inside an interpolation changes, only that text node is updated.
Attribute bindings
Prefix an attribute with : to bind it to an expression:
<img :src="avatarUrl()" :alt="userName()" />
<button :class="isActive() ? 'active' : ''">Save</button>
<input type="checkbox" :checked="done()" />
The binding re-evaluates whenever its signals change. If the expression evaluates to
null, undefined, or false, the attribute is removed; otherwise its value is
set to String(value).
Event handlers
Prefix an event name with @ to attach a handler. Several forms are accepted:
<!-- a function reference -->
<button @click="increment">+</button>
<!-- an inline arrow function (receives the event) -->
<input @input="(e) => setName(e.target.value)" />
<!-- a statement; `event` is available inside it -->
<button @click="setCount(0)">Reset</button>
Events on native elements use event delegation under the hood, so handlers are efficient even across large lists.
:::tip Component events
Putting @event on a component (a PascalCase tag) doesn't attach a DOM listener —
it passes the handler to the child as an on<Event> prop. See
Component events.
:::