Looping

{#each} block allows you to loop only array or array-like object (i.e. it has a .length property).

Here are some examples if you want to loop through data structures besides array.

Looping a map

You can use spread operator [...value] for Map to get an array of key value pairs.

<script>
	const map = new Map([
		['.svelte', 'Svelte'],
		['.js', 'JavaScript']
	]);
</script>

{#each [...map] as [key, value]}
	<div>
		{key}: {value}
	</div>
{/each}

Both Map.keys() and Map.values() method return an iterable. To use {#each} with iterable, you can use spread operator [...value] on the iterable.

<script>
	const map = new Map([
		['.svelte', 'Svelte'],
		['.js', 'JavaScript']
	]);
</script>

{#each [...map.keys()] as key}
	<div>
		{key}
	</div>
{/each}

{#each [...map.values()] as value}
	<div>
		{value}
	</div>
{/each}

Looping a set

You can use spread operator [...value] for Set to get an array of items.

<script>
	const set = new Set(['.svelte', '.js']);
</script>

{#each [...set] as item}
	<div>
		{item}
	</div>
{/each}

Looping a string

String is considered an array-like object as it has .length property.

<script>
	const string = 'Svelte';
</script>

{#each string as character}
	<div>
		{character}
	</div>
{/each}

Looping a generator function

Generator function function* returns a generator object, which conforms to both the iterable protocol and the iterator protocol.

To use {#each} with generator function, you can use spread operator [...value] on the generator.

<script>
	function* generator() {
		yield '.svelte';
		yield '.js';
	}
</script>

{#each [...generator()] as item}
	<div>
		{item}
	</div>
{/each}

Binding to a spread item

Once you spread a Map, Set, Generator, or any Iterable, you are creating a new array, and therefore binding (bind:) with the item may not work anymore.

<script>
	const map = new Map([
		['.svelte', 'Svelte'],
		['.js', 'JavaScript']
	]);
</script>

{#each [...map] as [key, value]}
	<!-- You can't change the value of the input, nor the value in the map -->
	<input bind:value />
{/each}

To workaround this, you can use on:input listener

<script>
	const map = new Map([
		['.svelte', 'Svelte'],
		['.js', 'JavaScript']
	]);
</script>

{#each [...map] as [key, value]}
	<input
		{value}
		on:input={(event) => {
			map.set(key, event.currentTarget.value);
			map = map;
		}}
	/>
{/each}
Published: