Svelte – Conditions and For Loops – If, Else, Each and Await blocks

Total
0
Shares

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 –

  1. A promise variable is created which holds the reference to the async function.
  2. 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.
  3. 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 of then block.
  4. 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}

    Tweet this to help others

Live Demo

Open Live Demo