How to simulate a for loop in Svelte templates
By Flavio Copes
Learn how to simulate a for loop in Svelte templates with the each block and the Array(n) syntax to repeat a block a number of times based on a variable.
Svelte templates don’t have a for loop, but you can simulate one by combining the each block with an array created on the fly using Array(n).
Let’s start from what Svelte gives us. Templates offer the fantastic each block that lets us iterate on an array, or anything that is iterable:
<script>
let goodDogs = ['Roger', 'Syd']
</script>
{#each goodDogs as goodDog}
<li>{goodDog}</li>
{/each}
But what if you want to repeat a block for a few times, based on a variable? Let’s say we have the rows variable that holds a number, and we want to use that as the loop variable.
We can do what we need by creating an array, using the Array(n) syntax. This will create an array, initializing it with n items:
{#each Array(rows) as _, row}
{row}
{/each}
How does this work?
Array(rows) creates an array with rows empty slots. The each block only cares about its length, so it repeats the markup rows times.
Every item in that array is undefined, and that’s why we name it _. It’s a convention that says “I’m not using this value”.
The second variable, row, is the index. That’s the one we actually use. It goes from 0 to rows - 1.
If you want to count from 1, add 1 to the index:
{#each Array(rows) as _, row}
<p>Row {row + 1}</p>
{/each}
With rows = 3 this renders “Row 1”, “Row 2”, “Row 3”.
And since rows can be reactive, changing it re-renders the block with the new count. That’s your dynamic for loop.
An alternative syntax
The each block accepts any array-like object, meaning anything with a length property. So this works too, without creating an array at all:
{#each { length: rows } as _, row}
<p>Row {row + 1}</p>
{/each}
Pick the one you find more readable. I lean towards Array(rows) because it looks more familiar.
Watch out for the item value
The pitfall with Array(rows) is trying to use the item itself:
{#each Array(3) as item}
<p>{item}</p>
{/each}
Every item is undefined, since the slots are empty. Only the length is real. Stick to the index variable.
If you do need actual values in the array, fill it before looping:
{#each Array(3).fill('Roger') as dog}
<p>{dog}</p>
{/each}
fill() puts the same value in every slot, so now the items are usable.