In this article we will learn how to use conditions and loops in Svelte. We will use if
, else
, elseif
conditions along with for
& each
loop blocks. We will also see the use of Await
block to handle asynchronous rendering.
Svelte Conditions
Conditions are the important part of any coding language. Without them it’s impossible to write codes. Here we will see all the conditions which we can use to render html selectively.
if
Block
Let’s start with if
block. An if
block renders the html under it when the condition is true. The syntax of using it is –
{#if condition} // Block to render like div {/if} // if closed
else
Block
When if
condition is not satisfied then else
block is rendered. It has no condition as it is applicable to all for which if
condition is not true.
{:else} // Block to render
Notice, that it starts with :
and not #
. Also there is no closing tag. This is because the else
is also the part of entire if
hierarchy. So, there will be only one closing tag after the end of all related if
, else
, elseif
etc. and that is closing /if
.
else if
Block
This is similar to else
block, only difference is that we can add a condition here.
{:else if condition} // Block to render
Using Conditions in Code
Here is a code example using all conditions –
<script> let weapon = 'Hammer' </script> {#if weapon === "Hammer"} <p>I am Thor</p> {:else if weapon === "Shield"} <p>I am Captain America</p> {:else if weapon === "Suit"} <p>I am Ironman</p> {:else if weapon === "Metals"} <p>I am Magneto</p> {:else} <p>I am Superman</p> {/if}
Svelte Loops
Svelte has one loop block which caters all the needs, each
loop. This is similar to foreach
loop of javascript. The syntax is –
{#each Array as Item, index (key)} // Block to run in loop {/each}
Here –
-
Array
is the name of array variable on which we have to run the loop. -
Item
is the single item of the array which we got from loop. -
index
is the index of array item. -
key
is used to let svelte understand each block in the loop. It helps in re-rendering of blocks properly. It needs to be unique for each loop cycle. Learn about the significance of key here.
You can skip index
if you don’t need it anywhere in your block. Then the loop structure will become –
{#each Array as Item (key)} // Block to run in loop {/each}
Example using Loop Block
<script> let superheroes = [ {id: 1, name: 'Superman'}, {id: 2, name: 'Batman'}, {id: 3, name: 'Cyborg'}, {id: 4, name: 'Wonder Woman'}, {id: 5, name: 'Van Helsing'}, {id: 6, name: 'Constantine'}, {id: 7, name: 'Aquaman'}, {id: 8, name: 'Night Crawler'}, ] </script> /** * superheroes - Array * singleHero - Item * index - index * singleHero.id - key */ {#each superheroes as singleHero, index (singleHero.id)} <p>Name: {singleHero.name}</p> {/each}
Svelte await
, then
, catch
Block
Await block is used to do asynchronous tasks. Suppose you are requesting data from server and till the request get completed, you want to show a loading animation then this block comes in handy. It works in this way –
- A promise variable is created which holds the reference to the async function.
- The await block use this promise to determine if the request is completed on not. Till the request is under processing the html in this block runs.
- After await, there is another block
then
which runs when the request is completed and function returns the response from server. You can use this response in the html ofthen
block. - Next is the
catch
block which gets executed when there is some error in processing request.
The syntax is –
{#await promise} <p>...Loading Animation</p> {:then number} <p>This is the response - {number}</p> {:catch error} <p style="color: red"> This is error - {error.message} </p> {/await}
Example using await
, then
, catch
blocks
<script> let ageFunction = async () => { const res = await fetch( 'https://svelte.dev/tutorial/random-number' ) const text = await res.text(); if (res.ok) { return text; } else { throw new Error(text); } } let promise = ageFunction(); </script> {#await promise} <p>Your age is - ... Loading</p> {:then response} <p>Your age is - {response}</p> {:catch error} <p>Error - {error.message}</p> {/await}
promise
holds the reference to the async
function while response
in then
block holds the value returned by function. In this case it’s a random number.
Complete Code Example
<script> let superheroes = [ { id: 1, name: "Superman" }, { id: 2, name: "Batman" }, { id: 3, name: "Cyborg" }, { id: 4, name: "Wonder Woman" }, { id: 5, name: "Van Helsing" }, { id: 6, name: "Constantine" }, { id: 7, name: "Aquaman" }, { id: 8, name: "Night Crawler" } ]; let weapon = "Hammer"; let asyncFunc = async () => { const res = await fetch("https://svelte.dev/tutorial/random-number"); const text = await res.text(); if (res.ok) { return text; } else { throw new Error(text); } }; let promise; //= asyncFunc(); function getAgeAgain() { promise = asyncFunc(); } </script> <h3>Testing Conditions</h3> <p> Select one <select bind:value={weapon}> <option>Hammer</option> <option>Suit</option> <option>Shield</option> <option>Lasers</option> <option>Strength</option> <option>Air blow</option> </select> </p> {#if weapon === 'Hammer'} <p>Running if block - Thor</p> {:else if weapon === 'Suit'} <p>Running else if block - Ironman</p> {:else if weapon === 'Shield'} <p>Running else if block - Captain America</p> {:else} <p>Running else block - Superman</p> {/if} <hr /> <h3>Testing Loop</h3> <table style={'width: 100%'}> <!-- This loop will run 2 times because there are 2 elements in array [1,2] It is used to create 2 rows in table. --> {#each [1,2] as row (row)} <tr> <!-- This loop will run over superheroes array twice. First time over half elements and second time over another half. This is controlled by javascript slice function which creates a subset of array. 1st parameter is starting index and second is end index. End index value is not included. Here we are using a logic - (row-1)*4 as start index and row*4 as end index. In 1st iteration of above loop - row = 1, so (row-1)*4 = (1-1)*4 = 0 row*4 = 1*4 = 4, so array slice will return a subset of superheroes array from element 0 to 4(excluding) i.e. = [ { id: 1, name: "Superman" }, { id: 2, name: "Batman" }, { id: 3, name: "Cyborg" }, { id: 4, name: "Wonder Woman" } ] In 2nd iteration row = 2, so (row-1)*4 = (2-1)*4 = 4 row*4 = 2*4 = 8, --> {#each superheroes.slice((row-1)*4, row*4) as singleHero, index (singleHero.id)} <td>{singleHero.id}. {singleHero.name}</td> {/each} </tr> {/each} </table> <hr /> <h3>Testing Await Block</h3> <p> A random number is coming from API. Also it throws errors randomly. So try multiple times using this button - <button on:click={getAgeAgain}>Get Age Again</button> </p> {#await promise} <p>Your age = ... Loading</p> {:then res} <p>Your age = {res}</p> {:catch error} <p>This is error = {error.message}</p> {/await}