Skip to content

Commit f14f11f

Browse files
author
Rich Harris
committed
better each block example, showing interactivity etc
1 parent 4bb2ad3 commit f14f11f

File tree

3 files changed

+139
-67
lines changed

3 files changed

+139
-67
lines changed

content/tutorial/01-svelte/04-logic/04-each-blocks/README.md

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,54 @@
22
title: Each blocks
33
---
44

5-
If you need to loop over lists of data, use an `each` block:
5+
When building user interfaces you'll often find yourself working with lists of data. In this exercise, we've repeated the `<button>` markup multiple times — changing the colour each time — but there's still more to add.
6+
7+
Instead of laboriously copying, pasting and editing, we can get rid of all but the first button, then use an `each` block:
68

79
```svelte
810
/// file: App.svelte
9-
<ul>
10-
+++{#each cats as cat}+++
11-
<li>
12-
<a href="https://www.youtube.com/watch?v={cat.id}">
13-
{cat.name}
14-
</a>
15-
</li>
11+
<div>
12+
+++{#each colors as color}+++
13+
<button
14+
aria-current="{selected === 'red' ? 'true' : undefined}"
15+
aria-label="red"
16+
style="background: red"
17+
on:click={() => selected = 'red'}
18+
></button>
1619
+++{/each}+++
17-
</ul>
20+
</div>
1821
```
1922

20-
> The expression (`cats`, in this case) can be any array or array-like object (i.e. it has a `length` property). You can loop over generic iterables with `each [...iterable]`.
23+
> The expression (`colors`, in this case) can be any array or array-like object (i.e. it has a `length` property). You can loop over generic iterables with `each [...iterable]`.
2124
22-
You can get the current _index_ as a second argument, like so:
25+
Now we need to use the `color` variable in place of `"red"`:
2326

2427
```svelte
2528
/// file: App.svelte
26-
{#each cats as cat+++, i}+++
27-
<li>
28-
<a href="https://www.youtube.com/watch?v={cat.id}">
29-
+++{i + 1}:+++ {cat.name}
30-
</a>
31-
</li>
32-
{/each}
29+
<div>
30+
{#each colors as color}
31+
<button
32+
aria-current="{selected === +++color+++ ? 'true' : undefined}"
33+
aria-label=+++{color}+++
34+
style="background: +++{color}+++"
35+
on:click={() => selected = +++color+++}
36+
></button>
37+
{/each}
38+
</div>
3339
```
3440

35-
If you prefer, you can use destructuring — `each cats as { id, name }` — and replace `cat.id` and `cat.name` with `id` and `name`.
41+
You can get the current _index_ as a second argument, like so:
42+
43+
```svelte
44+
/// file: App.svelte
45+
<div>
46+
{#each colors as color, +++i}+++
47+
<button
48+
aria-current="{selected === color ? 'true' : undefined}"
49+
aria-label={color}
50+
style="background: {color}"
51+
on:click={() => selected = color}
52+
>+++{i + 1}+++</button>
53+
{/each}
54+
</div>
55+
```
Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,63 @@
11
<script>
2-
let cats = [
3-
{
4-
id: 'J---aiyznGQ',
5-
name: 'Keyboard Cat'
6-
},
7-
{
8-
id: 'z_AbfPXTKms',
9-
name: 'Maru'
10-
},
11-
{
12-
id: 'OUtn3pvWmpg',
13-
name: 'Henri The Existential Cat'
14-
}
15-
];
2+
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
3+
let selected = colors[0];
164
</script>
175

18-
<h1>The Famous Cats of YouTube</h1>
19-
20-
<ul>
21-
<!-- open each block -->
22-
<li>
23-
<a href="https://www.youtube.com/watch?v={cat.id}">
24-
{cat.name}
25-
</a>
26-
</li>
27-
<!-- close each block -->
28-
</ul>
6+
<h1 style="color: {selected}">Pick a colour</h1>
7+
8+
<div>
9+
<button
10+
aria-current="{selected === 'red' ? 'true' : undefined}"
11+
aria-label="red"
12+
style="background: red"
13+
on:click={() => selected = 'red'}
14+
></button>
15+
16+
<button
17+
aria-current="{selected === 'orange' ? 'true' : undefined}"
18+
aria-label="orange"
19+
style="background: orange"
20+
on:click={() => selected = 'orange'}
21+
></button>
22+
23+
<button
24+
aria-current="{selected === 'yellow' ? 'true' : undefined}"
25+
aria-label="yellow"
26+
style="background: yellow"
27+
on:click={() => selected = 'yellow'}
28+
></button>
29+
30+
<!-- TODO add the rest of the colours -->
31+
<button></button>
32+
<button></button>
33+
<button></button>
34+
<button></button>
35+
</div>
36+
37+
<style>
38+
h1 {
39+
transition: color 0.2s;
40+
}
41+
42+
div {
43+
display: grid;
44+
grid-template-columns: repeat(7, 1fr);
45+
grid-gap: 5px;
46+
max-width: 400px;
47+
}
48+
49+
button {
50+
aspect-ratio: 1;
51+
border-radius: 50%;
52+
background: var(--color, #fff);
53+
transform: translate(-2px,-2px);
54+
filter: drop-shadow(2px 2px 3px rgba(0,0,0,0.2));
55+
transition: all 0.1s;
56+
}
57+
58+
button[aria-current="true"] {
59+
transform: none;
60+
filter: none;
61+
box-shadow: inset 3px 3px 4px rgba(0,0,0,0.2);
62+
}
63+
</style>
Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,45 @@
11
<script>
2-
let cats = [
3-
{
4-
id: 'J---aiyznGQ',
5-
name: 'Keyboard Cat'
6-
},
7-
{
8-
id: 'z_AbfPXTKms',
9-
name: 'Maru'
10-
},
11-
{
12-
id: 'OUtn3pvWmpg',
13-
name: 'Henri The Existential Cat'
14-
}
15-
];
2+
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
3+
let selected = colors[0];
164
</script>
175

18-
<h1>The Famous Cats of YouTube</h1>
6+
<h1 style="color: {selected}">Pick a colour</h1>
197

20-
<ul>
21-
{#each cats as { id, name }, i}
22-
<li>
23-
<a href="https://www.youtube.com/watch?v={id}">
24-
{i + 1}: {name}
25-
</a>
26-
</li>
8+
<div>
9+
{#each colors as color, i}
10+
<button
11+
aria-current="{selected === color ? 'true' : undefined}"
12+
aria-label={color}
13+
style="background: {color}"
14+
on:click={() => selected = color}
15+
>{i + 1}</button>
2716
{/each}
28-
</ul>
17+
</div>
18+
19+
<style>
20+
h1 {
21+
transition: color 0.2s;
22+
}
23+
24+
div {
25+
display: grid;
26+
grid-template-columns: repeat(7, 1fr);
27+
grid-gap: 5px;
28+
max-width: 400px;
29+
}
30+
31+
button {
32+
aspect-ratio: 1;
33+
border-radius: 50%;
34+
background: var(--color, #fff);
35+
transform: translate(-2px,-2px);
36+
filter: drop-shadow(2px 2px 3px rgba(0,0,0,0.2));
37+
transition: all 0.1s;
38+
}
39+
40+
button[aria-current="true"] {
41+
transform: none;
42+
filter: none;
43+
box-shadow: inset 3px 3px 4px rgba(0,0,0,0.2);
44+
}
45+
</style>

0 commit comments

Comments
 (0)