diff --git a/src/lib/client/superForm.ts b/src/lib/client/superForm.ts index f18c1aa3..8010f9a1 100644 --- a/src/lib/client/superForm.ts +++ b/src/lib/client/superForm.ts @@ -1,6 +1,6 @@ /* eslint-disable dci-lint/atomic-role-binding */ import type { TaintedFields, SuperFormValidated, SuperValidated } from '$lib/superValidate.js'; -import type { ActionResult, Page, SubmitFunction } from '@sveltejs/kit'; +import type { ActionResult, BeforeNavigate, Page, SubmitFunction } from '@sveltejs/kit'; import { derived, get, @@ -383,6 +383,30 @@ try { // No Storybook } +const onDestroyCallbacks = new Set<() => void>(); +let onDestroyInited = false; +const initOnDestroyHandler = () => { + if (onDestroyInited) return; + onDestroyInited = true; + onDestroy(() => { + for (const callback of onDestroyCallbacks) { + callback(); + } + }); +}; + +const beforeNavigateCallbacks = new Set<(nav: BeforeNavigate) => Promise>(); +let beforeNavigateInited = false; +const initBeforeNavigateHandler = () => { + if (beforeNavigateInited) return; + beforeNavigateInited = true; + beforeNavigate((nav: BeforeNavigate) => { + for (const callback of beforeNavigateCallbacks) { + callback(nav); + } + }); +}; + ///////////////////////////////////////////////////////////////////// /** @@ -404,6 +428,9 @@ export function superForm< // To check if a full validator is used when switching options.validators dynamically let initialValidator: FormOptions['validators'] | undefined = undefined; + initOnDestroyHandler(); + initBeforeNavigateHandler(); + { if (options.legacy ?? LEGACY_MODE) { if (options.resetForm === undefined) options.resetForm = false; @@ -518,7 +545,7 @@ export function superForm< ///// From here, form is properly initialized ///// - onDestroy(() => { + onDestroyCallbacks.add(() => { Unsubscriptions_unsubscribe(); NextChange_clear(); EnhancedForm_destroy(); @@ -1350,7 +1377,7 @@ export function superForm< // Tainted check const defaultMessage = 'Leave page? Changes that you made may not be saved.'; let forceRedirection = false; - beforeNavigate(async (nav) => { + beforeNavigateCallbacks.add(async (nav: BeforeNavigate) => { if (options.taintedMessage && !Data.submitting && !forceRedirection) { if (Tainted_isTainted()) { const { taintedMessage } = options; diff --git a/src/routes/(v2)/v2/Navigation.svelte b/src/routes/(v2)/v2/Navigation.svelte index 1aeebb3f..184754e8 100644 --- a/src/routes/(v2)/v2/Navigation.svelte +++ b/src/routes/(v2)/v2/Navigation.svelte @@ -14,6 +14,7 @@ 'issue-337-checkboxes', 'issue-345', 'letters', + 'multiple-forms', 'multiple-files', 'multistep-client', 'multistep-server', diff --git a/src/routes/(v2)/v2/multiple-forms/+page.server.ts b/src/routes/(v2)/v2/multiple-forms/+page.server.ts new file mode 100644 index 00000000..573afce2 --- /dev/null +++ b/src/routes/(v2)/v2/multiple-forms/+page.server.ts @@ -0,0 +1,42 @@ +import { zod } from '$lib/adapters/zod.js'; +import { superValidate } from '$lib/server/index.js'; +import { type Actions } from '@sveltejs/kit'; +import { schema } from './schema.js'; + +const items = [ + { + id: 1, + label: 'One' + }, + { + id: 2, + label: 'Two' + }, + { + id: 3, + label: 'Three' + } +]; + +export const load = async () => { + const item_forms = await Promise.all( + items.map((item) => + superValidate(item, zod(schema), { + id: item.id.toString() + }) + ) + ); + + return { item_forms }; +}; + +export const actions: Actions = { + async default() { + items.push({ + id: items.length + 1, + label: (items.length + 1).toString() + }); + + return { success: true }; + } +}; diff --git a/src/routes/(v2)/v2/multiple-forms/+page.svelte b/src/routes/(v2)/v2/multiple-forms/+page.svelte new file mode 100644 index 00000000..26ba0fe2 --- /dev/null +++ b/src/routes/(v2)/v2/multiple-forms/+page.svelte @@ -0,0 +1,24 @@ + + +{#each superforms as form (form.formId)} +
+{/each} + + + +
\ No newline at end of file diff --git a/src/routes/(v2)/v2/multiple-forms/Form.svelte b/src/routes/(v2)/v2/multiple-forms/Form.svelte new file mode 100644 index 00000000..c68815f4 --- /dev/null +++ b/src/routes/(v2)/v2/multiple-forms/Form.svelte @@ -0,0 +1,17 @@ + + +
+
+ + \ No newline at end of file diff --git a/src/routes/(v2)/v2/multiple-forms/schema.ts b/src/routes/(v2)/v2/multiple-forms/schema.ts new file mode 100644 index 00000000..97ada301 --- /dev/null +++ b/src/routes/(v2)/v2/multiple-forms/schema.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; + +export const schema = z.object({ + id: z.number(), + label: z.string() +});