Skip to content

Commit 42bf6da

Browse files
TommertomTommertom
authored andcommitted
Removed server forms and added client forms
1 parent 8ea63f0 commit 42bf6da

File tree

9 files changed

+434
-316
lines changed

9 files changed

+434
-316
lines changed

demo-app/src/lib/components/Menu.svelte

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
33
import { goto } from '$app/navigation';
4+
import { dev } from '$app/environment';
45
56
import { pwaBeforeInstallPrompt, canInstall } from '$lib/services/pwa';
67
import { showMenu } from '$lib/services/menu';
@@ -138,15 +139,13 @@
138139
<p>
139140
Raise issues on Github - <a
140141
href="https://github.com/Tommertom/svelte-ionic-app/issues"
141-
target="_new">https://github.com/Tommertom/svelte-ionic-app/issues</a
142-
>
142+
target="_new">https://github.com/Tommertom/svelte-ionic-app/issues</a>
143143
</p>
144144
<br />
145145
<p>
146146
Join <a
147147
href="https://discordapp.com/channels/520266681499779082/1049388501629681675"
148-
target="_new">Ionic-Svelte channel</a
149-
> on Ionic's official discord
148+
target="_new">Ionic-Svelte channel</a> on Ionic's official discord
150149
</p>
151150
<br /><br />
152151
<p>Thanks!!! Tommertom</p>
@@ -162,8 +161,7 @@
162161
}}
163162
on:click={() => {
164163
inlineModalOpen = false;
165-
}}
166-
>
164+
}}>
167165
Close modal
168166
</ion-button>
169167
vite v4.
@@ -186,8 +184,7 @@
186184
window.gtag('event', 'Feedback open');
187185
inlineModalOpen = true;
188186
}}
189-
slot="end">About...</ion-button
190-
>
187+
slot="end">About...</ion-button>
191188
</ion-toolbar>
192189
</ion-header>
193190
<ion-content>
@@ -199,8 +196,7 @@
199196
}}
200197
on:click={() => {
201198
closeAndNavigate(menuItem.url);
202-
}}
203-
>
199+
}}>
204200
<ion-icon icon={menuItem.icon} slot="start" color={getRandomColor()} />
205201
<ion-label>{menuItem.label}</ion-label>
206202
</ion-item>
@@ -223,8 +219,7 @@
223219
on:click={() => {
224220
const prompt = $pwaBeforeInstallPrompt;
225221
prompt.prompt();
226-
}}
227-
>
222+
}}>
228223
<ion-icon icon={allIonicIcons['download']} slot="start" />
229224
<ion-label>Install this app as PWA</ion-label>
230225
</ion-item>
@@ -241,8 +236,7 @@
241236
//@ts-ignore
242237
window.gtag('event', 'github-svelte-ionic-app');
243238
window.open('https://github.com/Tommertom/svelte-ionic-app', '_blank');
244-
}}
245-
>
239+
}}>
246240
<ion-icon icon={allIonicIcons['star']} slot="start" />
247241
<ion-label>Go to GitHub for this app</ion-label>
248242
</ion-item>

demo-app/src/routes/components/Inputs/+page.server.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

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

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
11
<script lang="ts">
2-
import { applyAction, enhance, type SubmitFunction } from '$app/forms';
3-
import { page } from '$app/stores';
42
import SourceButton from '$lib/components/SourceButton.svelte';
53
import { alertController, IonPage } from 'ionic-svelte';
6-
import type { ActionData } from './$types';
4+
import { onMount } from 'svelte';
75
8-
const patchForm: SubmitFunction = () => {
9-
return async ({ result }) => {
10-
await applyAction(result);
11-
};
12-
};
6+
import { accountSchema as schema } from './account.interface';
7+
import { enhance, getFormWritable, validate } from './spa-enhance';
138
14-
export let form: ActionData;
9+
const form = getFormWritable();
1510
16-
$: console.log('Form received', form);
17-
$: console.log('Page form', $page.form);
11+
$: console.log('Form received', $form);
1812
19-
$: if (form?.success) {
13+
$: if ($form?.success) {
2014
const controller = alertController
2115
.create({
2216
header: 'Account Created',
23-
message: `Created account for: <b>${form.formData.firstName} ${form.formData.lastName}</b>`,
17+
message: `Created account for: <b>${$form.data.firstName} ${$form.data.lastName}</b>`,
2418
buttons: [
2519
{
2620
text: 'OK'
@@ -30,7 +24,7 @@
3024
.then((alert) => alert.present());
3125
}
3226
33-
$: if (form !== null && !form?.success) {
27+
$: if ($form !== null && !$form?.success) {
3428
const controller = alertController
3529
.create({
3630
header: 'Account Not Created',
@@ -43,6 +37,10 @@
4337
})
4438
.then((alert) => alert.present());
4539
}
40+
41+
onMount(() => {
42+
console.log('Validate', validate);
43+
});
4644
</script>
4745

4846
<svelte:head>
@@ -63,22 +61,24 @@
6361
</ion-header>
6462

6563
<ion-content fullscreen class="ion-padding">
66-
<form method="POST" use:enhance={patchForm}>
64+
<form use:enhance={{ form, schema }} id="accountform">
6765
<ion-list lines="full" class="ion-no-margin ion-no-padding">
68-
<ion-item>
66+
<ion-item class:ion-invalid={$form?.errors?.firstName}>
6967
<ion-label position="stacked">
7068
First Name
7169
<ion-text color="danger">*</ion-text>
7270
</ion-label>
73-
<ion-input name="firstName" type="text" value={form?.formData?.firstName ?? ''} />
71+
<ion-input name="firstName" type="text" value={$form?.data.firstName ?? ''} />
72+
<ion-note slot="error">First name must be not empty and valid</ion-note>
7473
</ion-item>
7574

76-
<ion-item>
75+
<ion-item class:ion-invalid={$form?.errors?.lastName}>
7776
<ion-label position="stacked">
7877
Last Name
7978
<ion-text color="danger">*</ion-text>
8079
</ion-label>
8180
<ion-input name="lastName" required type="text" />
81+
<ion-note slot="error">FLast name must be not empty and valid</ion-note>
8282
</ion-item>
8383

8484
<ion-item>
@@ -107,9 +107,3 @@
107107
</form>
108108
</ion-content>
109109
</IonPage>
110-
111-
<style>
112-
input {
113-
color: red;
114-
}
115-
</style>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* eslint-disable @typescript-eslint/ban-ts-comment */
2+
3+
import { writable, type Writable } from "svelte/store";
4+
5+
// https://zod.dev/
6+
// https://morioh.com/p/cc9d89e8a10b
7+
import type { ZodTypeAny } from 'zod';
8+
9+
interface ErrorObject {
10+
[key: string]: string[];
11+
}
12+
export interface FormType {
13+
success?: boolean;
14+
errors?: ErrorObject;
15+
data: { [key: string]: string };
16+
validate?: () => void;
17+
}
18+
19+
export function getFormWritable() {
20+
return writable<FormType | null>(null);
21+
}
22+
23+
// export let validate: () => void;
24+
25+
// export function validateFromEvent(ev) {
26+
// console.log('sss', ev);
27+
// return true;
28+
// }
29+
30+
export function enhance(
31+
formNode: HTMLFormElement,
32+
bar: { form: Writable<FormType | null>; schema?: ZodTypeAny }
33+
) {
34+
const { form, schema } = bar;
35+
36+
function validateForm() {
37+
38+
function formToObject() {
39+
//@ts-ignore
40+
const form = document.forms[formNode.id];
41+
const formData = new FormData(form);
42+
const keys = Array.from(formData.keys());
43+
44+
const output: { [key: string]: string } = {};
45+
keys.forEach((key) => {
46+
output[key] = formData.get(key) as string;
47+
});
48+
49+
return output;
50+
}
51+
52+
let success = false;
53+
let errors: undefined | ErrorObject = undefined;
54+
let data = formToObject();
55+
56+
if (schema) {
57+
const result = schema.safeParse(data);
58+
success = result.success;
59+
60+
// add errros
61+
if (!result.success) {
62+
const errorsArray = result.error.errors.map((error) => {
63+
return {
64+
field: error.path[0],
65+
message: error.message
66+
};
67+
});
68+
69+
errors = errorsArray.reduce((acc, obj) => {
70+
//@ts-ignore
71+
if (!acc[obj.field]) {
72+
//@ts-ignore
73+
acc[obj.field] = [];
74+
}
75+
//@ts-ignore
76+
acc[obj.field].push(obj.message);
77+
return acc;
78+
}, {});
79+
}
80+
81+
if (result.success) data = result.data;
82+
}
83+
84+
form.set({
85+
success,
86+
errors,
87+
data,
88+
validate: validateForm
89+
});
90+
}
91+
92+
const submitHandler = (event: SubmitEvent) => {
93+
event.preventDefault();
94+
validateForm();
95+
};
96+
97+
formNode.addEventListener('submit', submitHandler);
98+
99+
100+
return {
101+
destroy() {
102+
formNode.removeEventListener('submit', submitHandler);
103+
}
104+
};
105+
}

0 commit comments

Comments
 (0)