Skip to content

Commit c35016d

Browse files
author
Rich Harris
committed
make form exercises nicer
1 parent d1a397f commit c35016d

File tree

15 files changed

+480
-179
lines changed

15 files changed

+480
-179
lines changed

content/tutorial/02-sveltekit/04-forms/01-the-form-element/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ Let's build a todo app. We've already got an in-memory database set up in `src/l
1313
+++<form method="POST">
1414
<label>
1515
add a todo:
16-
<input name="description" />
16+
<input
17+
name="description"
18+
autocomplete="off"
19+
/>
1720
</label>
1821
</form>+++
1922

content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/lib/server/database.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
const db = new Map();
44

55
export function getTodos(userid) {
6+
if (!db.get(userid)) {
7+
db.set(userid, [{
8+
id: crypto.randomUUID(),
9+
description: 'Learn SvelteKit',
10+
done: false
11+
}]);
12+
}
13+
614
return db.get(userid);
715
}
816

917
export function createTodo(userid, description) {
10-
if (!db.has(userid)) {
11-
db.set(userid, []);
12-
}
13-
1418
const todos = db.get(userid);
1519

1620
todos.push({

content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-a/src/routes/+page.svelte

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,52 @@
22
export let data;
33
</script>
44

5-
<h1>todos</h1>
6-
7-
<ul>
8-
{#each data.todos as todo (todo.id)}
9-
<li class="todo">
10-
{todo.description}
11-
</li>
12-
{/each}
13-
</ul>
5+
<div class="centered">
6+
<h1>todos</h1>
7+
8+
<ul class="todos">
9+
{#each data.todos as todo (todo.id)}
10+
<li>
11+
{todo.description}
12+
</li>
13+
{/each}
14+
</ul>
15+
</div>
16+
17+
<style>
18+
.centered {
19+
max-width: 20em;
20+
margin: 0 auto;
21+
}
22+
23+
label {
24+
width: 100%;
25+
}
26+
27+
input {
28+
flex: 1;
29+
}
30+
31+
span {
32+
flex: 1;
33+
}
34+
35+
button {
36+
border: none;
37+
background: url(./remove.svg) no-repeat 50% 50%;
38+
background-size: 1rem 1rem;
39+
cursor: pointer;
40+
height: 100%;
41+
aspect-ratio: 1;
42+
opacity: 0.5;
43+
transition: opacity 0.2s;
44+
}
45+
46+
button:hover {
47+
opacity: 1;
48+
}
49+
50+
.saving {
51+
opacity: 0.5;
52+
}
53+
</style>
Lines changed: 3 additions & 0 deletions
Loading

content/tutorial/02-sveltekit/04-forms/01-the-form-element/app-b/src/routes/+page.svelte

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,62 @@
22
export let data;
33
</script>
44

5-
<h1>todos</h1>
6-
7-
<form method="POST">
8-
<label>
9-
add a todo:
10-
<input name="description" />
11-
</label>
12-
</form>
13-
14-
<ul>
15-
{#each data.todos as todo (todo.id)}
16-
<li class="todo">
17-
{todo.description}
18-
</li>
19-
{/each}
20-
</ul>
5+
<div class="centered">
6+
<h1>todos</h1>
7+
8+
<form method="POST">
9+
<label>
10+
add a todo:
11+
<input
12+
name="description"
13+
autocomplete="off"
14+
/>
15+
</label>
16+
</form>
17+
18+
<ul class="todos">
19+
{#each data.todos as todo (todo.id)}
20+
<li>
21+
{todo.description}
22+
</li>
23+
{/each}
24+
</ul>
25+
</div>
26+
27+
<style>
28+
.centered {
29+
max-width: 20em;
30+
margin: 0 auto;
31+
}
32+
33+
label {
34+
width: 100%;
35+
}
36+
37+
input {
38+
flex: 1;
39+
}
40+
41+
span {
42+
flex: 1;
43+
}
44+
45+
button {
46+
border: none;
47+
background: url(./remove.svg) no-repeat 50% 50%;
48+
background-size: 1rem 1rem;
49+
cursor: pointer;
50+
height: 100%;
51+
aspect-ratio: 1;
52+
opacity: 0.5;
53+
transition: opacity 0.2s;
54+
}
55+
56+
button:hover {
57+
opacity: 1;
58+
}
59+
60+
.saving {
61+
opacity: 0.5;
62+
}
63+
</style>

content/tutorial/02-sveltekit/04-forms/02-named-form-actions/README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ The `<form>` element has an optional `action` attribute, which is similar to an
3030
<form method="POST" +++action="?/create"+++>
3131
<label>
3232
add a todo:
33-
<input name="description" />
33+
<input
34+
name="description"
35+
autocomplete="off"
36+
/>
3437
</label>
3538
</form>
3639
```
@@ -41,14 +44,14 @@ Next, we want to create a form for each todo, complete with a hidden `<input>` t
4144

4245
```svelte
4346
/// file: src/routes/+page.svelte
44-
<ul>
47+
<ul class="todos">
4548
{#each data.todos as todo (todo.id)}
46-
<li class="todo">
49+
<li>
4750
+++ <form method="POST" action="?/delete">
4851
<input type="hidden" name="id" value={todo.id} />
49-
<button aria-label="Mark as complete">✔</button>+++
50-
{todo.description}
51-
+++ </form>+++
52+
<span>{todo.description}</span>
53+
<button aria-label="Mark as complete" />
54+
</form>+++
5255
</li>
5356
{/each}
5457
</ul>

content/tutorial/02-sveltekit/04-forms/02-named-form-actions/app-b/src/routes/+page.svelte

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,66 @@
22
export let data;
33
</script>
44

5-
<h1>todos</h1>
6-
7-
<form method="POST" action="?/create">
8-
<label>
9-
add a todo:
10-
<input name="description" />
11-
</label>
12-
</form>
13-
14-
<ul>
15-
{#each data.todos as todo (todo.id)}
16-
<li class="todo">
17-
<form method="POST" action="?/delete">
18-
<input type="hidden" name="id" value={todo.id} />
19-
<button aria-label="Mark as complete">✔</button>
20-
21-
{todo.description}
22-
</form>
23-
</li>
24-
{/each}
25-
</ul>
5+
<div class="centered">
6+
<h1>todos</h1>
7+
8+
<form method="POST" action="?/create">
9+
<label>
10+
add a todo:
11+
<input
12+
name="description"
13+
autocomplete="off"
14+
/>
15+
</label>
16+
</form>
17+
18+
<ul class="todos">
19+
{#each data.todos as todo (todo.id)}
20+
<li>
21+
<form method="POST" action="?/delete">
22+
<input type="hidden" name="id" value={todo.id} />
23+
<span>{todo.description}</span>
24+
<button aria-label="Mark as complete" />
25+
</form>
26+
</li>
27+
{/each}
28+
</ul>
29+
</div>
30+
31+
<style>
32+
.centered {
33+
max-width: 20em;
34+
margin: 0 auto;
35+
}
36+
37+
label {
38+
width: 100%;
39+
}
40+
41+
input {
42+
flex: 1;
43+
}
44+
45+
span {
46+
flex: 1;
47+
}
48+
49+
button {
50+
border: none;
51+
background: url(./remove.svg) no-repeat 50% 50%;
52+
background-size: 1rem 1rem;
53+
cursor: pointer;
54+
height: 100%;
55+
aspect-ratio: 1;
56+
opacity: 0.5;
57+
transition: opacity 0.2s;
58+
}
59+
60+
button:hover {
61+
opacity: 1;
62+
}
63+
64+
.saving {
65+
opacity: 0.5;
66+
}
67+
</style>

content/tutorial/02-sveltekit/04-forms/03-form-validation/README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ The first line of defense is the browser's [built-in form validation](https://de
1010
/// file: src/routes/+page.svelte
1111
<form method="POST" action="?/create">
1212
<label>
13-
Add a todo
13+
add a todo
1414
<input
1515
name="description"
16+
autocomplete="off"
1617
+++required+++
1718
/>
1819
</label>
@@ -32,10 +33,6 @@ export function createTodo(userid, description) {
3233
throw new Error('todo must have a description');
3334
}+++
3435

35-
if (!db.has(userid)) {
36-
db.set(userid, []);
37-
}
38-
3936
const todos = db.get(userid);
4037

4138
+++ if (todos.find((todo) => todo.description === description)) {
@@ -97,6 +94,7 @@ In `src/routes/+page.svelte`, we can access the returned value via the `form` pr
9794
<input
9895
name="description"
9996
+++value={form?.description ?? ''}+++
97+
autocomplete="off"
10098
required
10199
/>
102100
</label>

content/tutorial/02-sveltekit/04-forms/03-form-validation/app-b/src/lib/server/database.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
const db = new Map();
44

55
export function getTodos(userid) {
6+
if (!db.get(userid)) {
7+
db.set(userid, [{
8+
id: crypto.randomUUID(),
9+
description: 'Learn SvelteKit',
10+
done: false
11+
}]);
12+
}
13+
614
return db.get(userid);
715
}
816

@@ -11,10 +19,6 @@ export function createTodo(userid, description) {
1119
throw new Error('todo must have a description');
1220
}
1321

14-
if (!db.has(userid)) {
15-
db.set(userid, []);
16-
}
17-
1822
const todos = db.get(userid);
1923

2024
if (todos.find((todo) => todo.description === description)) {

0 commit comments

Comments
 (0)