Svelte offer ways to express logic, which HTML doesn't. Rule of the thumb is
{# to start logic block (if, each, await)
{: for continuation logic block (else, then, catch)
{/ to close logic block
We use tag {#if condition}{/if} to do logical if. Here is some code example:
<script>
let user = { loggedIn: false };function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}
{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}
Use {:else} to do logical else. If else block will look like this
{#if [condition]}
...
{:else}
...
{/if}
A # character always indicates a block opening tag. A / character always indicates a block closing tag. A : character, as in {:else}, indicates a block continuation tag.
You can chain multiple condition using else if like this:
{#if [condition]}
...
{:else if [condition]}
...
{:else}
...
{/if}
If you need to loop over lists of data, use an each block:
<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>
<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>
You can get the current index as a second argument, like so:
{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}
If you prefer, you can use destructuring — each cats as { id, name }— and replace cat.id and cat.name with id and name.
{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}
When you add or remove something from each block, it will remove or add at the last position of data. But sometimes it's not what we want, for example when you use array operation slice(1), you want to remove first data without re-rendering/reset the rest. So in order to match the perspective we use keyed each to mark each generated object as unique like this:
{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}
instead of:
{#each things as thing}
<Thing current={thing.color}/>
{/each}
so when we remove first position of array, the component that is removed in the each block is also the first one not the last one, for interactive example you can check this https://svelte.dev/tutorial/keyed-each-blocks
Most web applications have to deal with asynchronous data at some point. Svelte makes it easy to await the value of directly in your markup. Here is the example of await block:
{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
For example:
<script>
let promise = exampleAsync();
async function exampleAsnyc() {
await new Promise(r => setTimeout(r, 2000)); // eg. hitting certain API
return Math.random()
}
function onClick() { promise = exampleAsync(); }
</script>
<button on:click="onClick">Click Me!</button>
{# to start logic block (if, each, await)
{: for continuation logic block (else, then, catch)
{/ to close logic block
If Blocks (decision/branch)
We use tag {#if condition}{/if} to do logical if. Here is some code example:
<script>
let user = { loggedIn: false };function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}
{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}
Else
Use {:else} to do logical else. If else block will look like this
{#if [condition]}
...
{:else}
...
{/if}
A # character always indicates a block opening tag. A / character always indicates a block closing tag. A : character, as in {:else}, indicates a block continuation tag.
Else if
You can chain multiple condition using else if like this:
{#if [condition]}
...
{:else if [condition]}
...
{:else}
...
{/if}
Each (looping)
If you need to loop over lists of data, use an each block:
<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>
<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>
You can get the current index as a second argument, like so:
{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}
If you prefer, you can use destructuring — each cats as { id, name }— and replace cat.id and cat.name with id and name.
{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}
Keyed each
When you add or remove something from each block, it will remove or add at the last position of data. But sometimes it's not what we want, for example when you use array operation slice(1), you want to remove first data without re-rendering/reset the rest. So in order to match the perspective we use keyed each to mark each generated object as unique like this:
{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}
instead of:
{#each things as thing}
<Thing current={thing.color}/>
{/each}
so when we remove first position of array, the component that is removed in the each block is also the first one not the last one, for interactive example you can check this https://svelte.dev/tutorial/keyed-each-blocks
Await Block (async calls)
Most web applications have to deal with asynchronous data at some point. Svelte makes it easy to await the value of directly in your markup. Here is the example of await block:
{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
For example:
<script>
let promise = exampleAsync();
async function exampleAsnyc() {
await new Promise(r => setTimeout(r, 2000)); // eg. hitting certain API
return Math.random()
}
function onClick() { promise = exampleAsync(); }
</script>
<button on:click="onClick">Click Me!</button>