|
|
---
|
|
|
title: Template syntax
|
|
|
---
|
|
|
|
|
|
Rather than reinventing the wheel, Svelte templates are built on foundations that have stood the test of time: HTML, CSS and JavaScript. There's very little extra stuff to learn.
|
|
|
|
|
|
|
|
|
### Tags
|
|
|
|
|
|
Tags allow you to bind data to your template. Whenever your data changes (for example after `component.a = 3`), the DOM updates automatically. You can use any JavaScript expression in templates, and it will also automatically update:
|
|
|
|
|
|
```html
|
|
|
<!-- { title: 'Template tags' } -->
|
|
|
<p>{a} + {b} = {a + b}</p>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
"a": 1,
|
|
|
"b": 2
|
|
|
}
|
|
|
```
|
|
|
|
|
|
You can also use tags in attributes:
|
|
|
|
|
|
```html
|
|
|
<!-- { title: 'Tags in attributes' } -->
|
|
|
<h1 style="color: {color};">{color}</h1>
|
|
|
<p hidden={hideParagraph}>You can hide this paragraph.</p>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
color: "steelblue",
|
|
|
hideParagraph: false
|
|
|
}
|
|
|
```
|
|
|
[Boolean attributes](https://www.w3.org/TR/html5/infrastructure.html#sec-boolean-attributes) like `hidden` will be omitted if the tag expression evaluates to false. Attributes will be removed from the element if their value is `undefined` or `null`.
|
|
|
|
|
|
### HTML
|
|
|
|
|
|
Ordinary tags render expressions as plain text. If you need your expression interpreted as HTML, wrap it in a special `@html` tag:
|
|
|
|
|
|
```html
|
|
|
<!-- { title: 'Triple tags' } -->
|
|
|
<p>This HTML: {content}</p>
|
|
|
<p>Renders as: {@html content}</p>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
content: "Some <b>bold</b> text."
|
|
|
}
|
|
|
```
|
|
|
|
|
|
As with regular tags, you can use any JavaScript expression in HTML tags, and it will automatically update the document when your data changes.
|
|
|
|
|
|
> HTML is **not** sanitized before it is rendered! If you are displaying user input, you are responsible for first sanitizing it. Not doing so potentially opens you up to XSS attacks.
|
|
|
|
|
|
|
|
|
### If blocks
|
|
|
|
|
|
Control whether or not part of your template is rendered by wrapping it in an if block.
|
|
|
|
|
|
```html
|
|
|
<!-- { repl: false } -->
|
|
|
{#if user.loggedIn}
|
|
|
<a href="/logout">log out</a>
|
|
|
{/if}
|
|
|
|
|
|
{#if !user.loggedIn}
|
|
|
<a href="/login">log in</a>
|
|
|
{/if}
|
|
|
```
|
|
|
|
|
|
You can combine the two blocks above with `{:else}`:
|
|
|
|
|
|
```html
|
|
|
<!-- { repl: false } -->
|
|
|
{#if user.loggedIn}
|
|
|
<a href="/logout">log out</a>
|
|
|
{:else}
|
|
|
<a href="/login">log in</a>
|
|
|
{/if}
|
|
|
```
|
|
|
|
|
|
You can also use `{:else if ...}`:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'If, else and else if' }-->
|
|
|
{#if x > 10}
|
|
|
<p>{x} is greater than 10</p>
|
|
|
{:else if 5 > x}
|
|
|
<p>{x} is less than 5</p>
|
|
|
{:else}
|
|
|
<p>{x} is between 5 and 10</p>
|
|
|
{/if}
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
x: 7
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### Each blocks
|
|
|
|
|
|
Iterate over lists of data:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Each blocks' }-->
|
|
|
<h1>Cats of YouTube</h1>
|
|
|
|
|
|
<ul>
|
|
|
{#each cats as cat}
|
|
|
<li><a target="_blank" href={cat.video}>{cat.name}</a></li>
|
|
|
{:else}
|
|
|
<li>No cats :(</li>
|
|
|
{/each}
|
|
|
</ul>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
cats: [
|
|
|
{
|
|
|
name: "Keyboard Cat",
|
|
|
video: "https://www.youtube.com/watch?v=J---aiyznGQ"
|
|
|
},
|
|
|
{
|
|
|
name: "Maru",
|
|
|
video: "https://www.youtube.com/watch?v=z_AbfPXTKms"
|
|
|
},
|
|
|
{
|
|
|
name: "Henri The Existential Cat",
|
|
|
video: "https://www.youtube.com/watch?v=OUtn3pvWmpg"
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Else is triggered when the list is empty.
|
|
|
|
|
|
You can access the index of the current element with *expression* as *name*, *index*:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Each block indexes' }-->
|
|
|
<div class="grid">
|
|
|
{#each rows as row, y}
|
|
|
<div class="row">
|
|
|
{#each columns as column, x}
|
|
|
<code class="cell">
|
|
|
{x + 1},{y + 1}:
|
|
|
<strong>{row[column]}</strong>
|
|
|
</code>
|
|
|
{/each}
|
|
|
</div>
|
|
|
{/each}
|
|
|
</div>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
columns: ["foo", "bar", "baz"],
|
|
|
rows: [
|
|
|
{ foo: "a", bar: "b", baz: "c" },
|
|
|
{ foo: "d", bar: "e", baz: "f" },
|
|
|
{ foo: "g", bar: "h", baz: "i" }
|
|
|
]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
> By default, if the list `a, b, c` becomes `a, c`, Svelte will *remove* the third block and *change* the second from `b` to `c`, rather than removing `b`. If that's not what you want, use a [keyed each block](docs#keyed-each-blocks).
|
|
|
|
|
|
You can use destructuring patterns on the elements of the array:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Each block destructuring' }-->
|
|
|
<h1>It's the cats of YouTube again</h1>
|
|
|
|
|
|
<ul>
|
|
|
{#each cats as {name, video} }
|
|
|
<li><a target="_blank" href={video}>{name}</a></li>
|
|
|
{/each}
|
|
|
</ul>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
cats: [
|
|
|
{
|
|
|
name: "Keyboard Cat",
|
|
|
video: "https://www.youtube.com/watch?v=J---aiyznGQ"
|
|
|
},
|
|
|
{
|
|
|
name: "Maru",
|
|
|
video: "https://www.youtube.com/watch?v=z_AbfPXTKms"
|
|
|
},
|
|
|
{
|
|
|
name: "Henri The Existential Cat",
|
|
|
video: "https://www.youtube.com/watch?v=OUtn3pvWmpg"
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### Await blocks
|
|
|
|
|
|
You can represent the three states of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — pending, fulfilled and rejected — with an `await` block:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Await blocks' }-->
|
|
|
<script>
|
|
|
const promise = new Promise(fulfil => {
|
|
|
setTimeout(() => fulfil(42), 3000);
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
{#await promise}
|
|
|
<p>wait for it...</p>
|
|
|
{:then answer}
|
|
|
<p>the answer is {answer}!</p>
|
|
|
{:catch error}
|
|
|
<p>well that's odd</p>
|
|
|
{/await}
|
|
|
```
|
|
|
|
|
|
If the expression in `{#await expression}` *isn't* a promise, Svelte skips ahead to the `then` section.
|
|
|
|
|
|
|
|
|
### Directives
|
|
|
|
|
|
Directives allow you to add special instructions for adding [event handlers](docs#event-handlers), [bindings](docs#bindings), [transitions](docs#transitions) and so on. We'll cover each of those in later stages of this guide – for now, all you need to know is that directives can be identified by the `:` character:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Element directives' }-->
|
|
|
<p>Count: {count}</p>
|
|
|
<button on:click="{() => count += 1}">+1</button>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
count: 0
|
|
|
}
|
|
|
```
|
|
|
|
|
|
> Technically, the `:` character is used to denote namespaced attributes in HTML. These will *not* be treated as directives, if encountered.
|
|
|
|
|
|
|
|
|
### Debug tags
|
|
|
|
|
|
To inspect data as it changes and flows through your app, use a `{@debug ...}` tag:
|
|
|
|
|
|
```html
|
|
|
<!--{ title: 'Debug tags' }-->
|
|
|
<input bind:value={name}>
|
|
|
|
|
|
{@debug name}
|
|
|
<h1>Hello {name}!</h1>
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
/* { hidden: true } */
|
|
|
{
|
|
|
name: 'world'
|
|
|
}
|
|
|
```
|
|
|
|
|
|
This will log the value of `name` whenever it changes. If your devtools are open, changing `name` will pause execution and open the debugger.
|
|
|
|
|
|
You can debug multiple values simultaneously (`{@debug foo, bar, baz}`), or use `{@debug}` to pause execution whenever the surrounding markup is updated.
|
|
|
|
|
|
> Debug tags only have an effect when compiling with the `dev: true` compiler option.
|