Skip to content

Commit 8ea63f0

Browse files
TommertomTommertom
Tommertom
authored and
Tommertom
committed
zod and form actions for demo app
1 parent 717ef1b commit 8ea63f0

File tree

6 files changed

+89
-34
lines changed

6 files changed

+89
-34
lines changed

demo-app/src/routes/components/Inputs/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
</script>
4747

4848
<svelte:head>
49-
<title>Ionic Companion - Inputs</title>
49+
<title>Ionic Companion - Inputs - with Form Actions and zod</title>
5050
</svelte:head>
5151

5252
<IonPage>

demo-app/src/routes/components/Select/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</script>
1919

2020
<svelte:head>
21-
<title>Ionic Companion - Select</title>
21+
<title>Ionic Companion - Select - with Form Actions and zod</title>
2222
</svelte:head>
2323

2424
<IonPage>
Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,46 @@
11
import type { PageServerLoad } from './$types';
22
import type { Actions } from './$types';
33

4+
import { accountSchema } from './account.interface';
5+
46
export const load = (async () => {
57
return {};
68
}) satisfies PageServerLoad;
79

810
export const actions = {
911
default: async ({ request }) => {
10-
const formData = Object.fromEntries(await request.formData())
1112

12-
const success = Math.random() > 0.3;
13-
const errors = {};
14-
Object.keys(formData).forEach(key => {
15-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
16-
//@ts-ignore
17-
errors[key] = Math.random() > 0.3;
18-
})
13+
let success = true;
14+
let errors = {};
15+
16+
const formBody = await request.formData();
17+
let formAsObject = Object.fromEntries(formBody);
18+
19+
const result = accountSchema.safeParse(formAsObject)
20+
console.log('newAccountSchema.safeParse result', formAsObject, result);
21+
if (!result.success) {
22+
/*
23+
Taken from - https://www.okupter.com/blog/sveltekit-form-validation-with-zod
1924
20-
console.log('Logging to vite window', formData, errors, success)
25+
Errors will be placed in an array of:
26+
{field:'name', message:'the message'}
27+
*/
28+
errors = result.error.errors.map((error) => {
29+
return {
30+
field: error.path[0],
31+
message: error.message
32+
};
33+
});
34+
console.log('newAccountSchema.safeParse errors', errors);
35+
success = false;
36+
}
2137

38+
if (result.success) {
39+
formAsObject = result.data;
40+
}
2241

23-
return { success, errors, formData }
42+
console.log('Logging to vite window', formAsObject, errors, success)
43+
return { success, errors, formData: formAsObject }
2444
}
2545

2646
} satisfies Actions

demo-app/static/assets/src/components/Inputs/+page.svelte

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,52 @@
11
<script lang="ts">
2-
import { enhance } from '$app/forms';
2+
import { applyAction, enhance, type SubmitFunction } from '$app/forms';
33
import { page } from '$app/stores';
44
import SourceButton from '$lib/components/SourceButton.svelte';
55
import { alertController, IonPage } from 'ionic-svelte';
66
import type { ActionData } from './$types';
77
8+
const patchForm: SubmitFunction = () => {
9+
return async ({ result }) => {
10+
await applyAction(result);
11+
};
12+
};
13+
814
export let form: ActionData;
915
1016
$: console.log('Form received', form);
1117
$: console.log('Page form', $page.form);
1218
13-
// $: if (form?.success) {
14-
// console.log('Processing form', form);
15-
// // event.preventDefault();
16-
// const controller = alertController
17-
// .create({
18-
// header: 'Account Created',
19-
// message: `Created account for: <b>${form.formData.firstName} ${form.formData.lastName}</b>`,
20-
// buttons: [
21-
// {
22-
// text: 'OK'
23-
// }
24-
// ]
25-
// })
26-
// .then((alert) => alert.present());
27-
// }
19+
$: if (form?.success) {
20+
const controller = alertController
21+
.create({
22+
header: 'Account Created',
23+
message: `Created account for: <b>${form.formData.firstName} ${form.formData.lastName}</b>`,
24+
buttons: [
25+
{
26+
text: 'OK'
27+
}
28+
]
29+
})
30+
.then((alert) => alert.present());
31+
}
32+
33+
$: if (form !== null && !form?.success) {
34+
const controller = alertController
35+
.create({
36+
header: 'Account Not Created',
37+
message: `There were some errors - see console.log`,
38+
buttons: [
39+
{
40+
text: 'OK'
41+
}
42+
]
43+
})
44+
.then((alert) => alert.present());
45+
}
2846
</script>
2947

3048
<svelte:head>
31-
<title>Ionic Companion - Inputs</title>
49+
<title>Ionic Companion - Inputs - with Form Actions and zod</title>
3250
</svelte:head>
3351

3452
<IonPage>
@@ -45,14 +63,14 @@
4563
</ion-header>
4664

4765
<ion-content fullscreen class="ion-padding">
48-
<form method="POST" use:enhance>
66+
<form method="POST" use:enhance={patchForm}>
4967
<ion-list lines="full" class="ion-no-margin ion-no-padding">
5068
<ion-item>
5169
<ion-label position="stacked">
5270
First Name
5371
<ion-text color="danger">*</ion-text>
5472
</ion-label>
55-
<ion-input name="firstName" type="text" value={form?.formData.firstName ?? ''} />
73+
<ion-input name="firstName" type="text" value={form?.formData?.firstName ?? ''} />
5674
</ion-item>
5775

5876
<ion-item>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// https://zod.dev/
2+
// https://morioh.com/p/cc9d89e8a10b
3+
import { z } from 'zod';
4+
5+
export const accountSchema = z.object({
6+
firstName: z.string().trim().min(3, { message: "first_name_too_short" }),
7+
lastName: z.string().trim().min(5, { message: "last_name_too_short" })
8+
});
9+
10+
// not used
11+
export type Account = z.infer<typeof accountSchema>;

demo-app/static/assets/src/components/Select/+page.svelte

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
<script lang="ts">
2-
import { enhance } from '$app/forms';
2+
import { applyAction, enhance, type SubmitFunction } from '$app/forms';
33
import { page } from '$app/stores';
44
import SourceButton from '$lib/components/SourceButton.svelte';
55
import { IonPage } from 'ionic-svelte';
66
import type { ActionData } from '../Inputs/$types';
77
8+
const patchForm: SubmitFunction = () => {
9+
return async ({ result }) => {
10+
await applyAction(result);
11+
};
12+
};
13+
814
export let form: ActionData;
915
1016
$: console.log('Form received', form);
1117
$: console.log('Page form', $page.form);
1218
</script>
1319

1420
<svelte:head>
15-
<title>Ionic Companion - Select</title>
21+
<title>Ionic Companion - Select - with Form Actions and zod</title>
1622
</svelte:head>
1723

1824
<IonPage>
@@ -29,7 +35,7 @@
2935
</ion-header>
3036

3137
<ion-content fullscreen>
32-
<form method="POST" action="/components/Inputs" use:enhance>
38+
<form method="POST" action="/components/Inputs" use:enhance={patchForm}>
3339
<ion-list>
3440
<ion-item>
3541
<ion-label>Pet</ion-label>

0 commit comments

Comments
 (0)