Skip to content

Commit 3f222fc

Browse files
committed
Redirect in SPA mode cancelled normal redirects, preventing applyAction.
1 parent d5f28a3 commit 3f222fc

File tree

12 files changed

+184
-9
lines changed

12 files changed

+184
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Fixed types for constraints, tainted and errors when using intersections and unions in schemas.
1313
- Fixed SuperDebug collapsed height by preventing global css leak.
14+
- Redirect in SPA mode cancelled normal redirects, preventing applyAction.
1415

1516
## [2.8.1] - 2024-03-07
1617

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
"sass": "^1.71.1",
172172
"svelte": "5.0.0-next.70",
173173
"svelte-check": "^3.6.6",
174+
"svelte-french-toast": "^1.2.0",
174175
"sveltekit-flash-message": "^2.4.4",
175176
"sveltekit-rate-limiter": "^0.4.3",
176177
"throttle-debounce": "^5.0.0",

pnpm-lock.yaml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/client/superForm.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,13 +1819,14 @@ export function superForm<
18191819
cancel
18201820
};
18211821

1822-
const unsubCheckforNav = STORYBOOK_MODE
1823-
? () => {}
1824-
: navigating.subscribe(($nav) => {
1825-
// Check for goto to a different route in the events
1826-
if (!$nav || $nav.from?.route.id === $nav.to?.route.id) return;
1827-
cancel();
1828-
});
1822+
const unsubCheckforNav =
1823+
STORYBOOK_MODE || !options.SPA
1824+
? () => {}
1825+
: navigating.subscribe(($nav) => {
1826+
// Check for goto to a different route in the events
1827+
if (!$nav || $nav.from?.route.id === $nav.to?.route.id) return;
1828+
cancel();
1829+
});
18291830

18301831
for (const event of formEvents.onResult) {
18311832
await event(data);

src/routes/(v2)/v2/Navigation.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
'issue-366',
4646
'issue-368',
4747
'zod-discriminated',
48-
'syncflash'
48+
'syncflash',
49+
'redirect-login'
4950
].sort();
5051
</script>
5152

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script>
2+
import { page } from '$app/stores';
3+
import { getFlash } from 'sveltekit-flash-message/client';
4+
5+
const flash = getFlash(page);
6+
7+
console.log('Flash in layout', JSON.stringify($flash));
8+
9+
// https://svelte-french-toast.com/
10+
import toast, { Toaster } from 'svelte-french-toast';
11+
12+
// Simple Toasts TODO: style and integrate in theme
13+
$: if ($flash) {
14+
switch ($flash.type) {
15+
case 'ok':
16+
toast.success($flash.message);
17+
break;
18+
case 'error':
19+
toast.error($flash.message);
20+
break;
21+
}
22+
23+
// Clear the flash message to avoid double-toasting.
24+
//$flash = undefined;
25+
}
26+
</script>
27+
28+
<p>{JSON.stringify($flash)}</p>
29+
30+
<Toaster />
31+
<slot />
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Please <a href="/v2/redirect-login/login">login here</a>.</p>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { redirect } from 'sveltekit-flash-message/server';
2+
import { message, superValidate } from '$lib/index.js';
3+
import { zod } from '$lib/adapters/zod.js';
4+
import { login_schema } from './schema.js';
5+
6+
export async function load() {
7+
return {
8+
form: await superValidate(zod(login_schema))
9+
};
10+
}
11+
12+
/**
13+
* Page form actions handlers
14+
*/
15+
export const actions = {
16+
/**
17+
* default() form handler
18+
* can be used only if other named actions not defined
19+
* better use named actions to keep it clear
20+
*/
21+
// default: async ({locals, request}) => {},
22+
23+
/**
24+
* handle signup form login
25+
*/
26+
login: async ({ request, cookies }) => {
27+
const form = await superValidate(request, zod(login_schema));
28+
29+
// Clientside validation failed
30+
if (!form.valid) {
31+
return message(form, { type: 'error', message: 'Login input wrong' }, { status: 400 });
32+
}
33+
34+
console.log('Login successful');
35+
36+
// Redirect to home and send login succesfully message
37+
return redirect(303, '/v2/redirect-login', { type: 'ok', message: 'Login success' }, cookies);
38+
}
39+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script lang="ts">
2+
import * as flashModule from 'sveltekit-flash-message/client';
3+
import { superForm } from '$lib/index.js';
4+
5+
export let data;
6+
7+
const { form, errors, enhance } = superForm(data.form, {
8+
syncFlashMessage: true,
9+
flashMessage: {
10+
module: flashModule
11+
},
12+
onError: 'apply',
13+
resetForm: false
14+
});
15+
</script>
16+
17+
<span class="page page-login">
18+
<main>
19+
<div class="page-container container-xxl">
20+
<div class="d-flex">
21+
<div class="w-lg-500px p-4 p-sm-10 p-lg-15 mx-auto">
22+
<form class="form w-100" method="POST" action="?/login" use:enhance>
23+
<div class="text-center mb-10">
24+
<div class="fv-row mb-10">
25+
<label class="form-label fs-6 fw-bold text-dark" for="emailInput">Email</label>
26+
<input
27+
class="form-control form-control-lg form-control-solid"
28+
type="text"
29+
name="email"
30+
id="emailInput"
31+
autocomplete="email"
32+
aria-invalid={$errors.email ? 'true' : undefined}
33+
bind:value={$form.email}
34+
/>
35+
{#if $errors.email}<div class="invalid-feedback">{$errors.email}</div>{/if}
36+
</div>
37+
38+
<div class="fv-row mb-10">
39+
<div class="d-flex flex-stack mb-2">
40+
<label class="form-label fw-bold text-dark fs-6 mb-0" for="passwordInput"
41+
>Password</label
42+
>
43+
</div>
44+
45+
<input
46+
class="form-control form-control-lg form-control-solid"
47+
type="password"
48+
name="password"
49+
id="passwordInput"
50+
autocomplete="off"
51+
aria-invalid={$errors.password ? 'true' : undefined}
52+
bind:value={$form.password}
53+
/>
54+
{#if $errors.password}<div class="invalid-feedback">{$errors.password}</div>{/if}
55+
</div>
56+
57+
<div class="text-center">
58+
<button type="submit" id="kt_sign_in_submit" class="btn btn-lg btn-apb w-100 mb-5">
59+
<span class="indicator-label">Continue</span>
60+
<!-- <span class="indicator-progress"
61+
>Please wait...
62+
<span class="spinner-border spinner-border-sm align-middle ms-2"></span></span
63+
> -->
64+
</button>
65+
</div>
66+
</div>
67+
</form>
68+
</div>
69+
</div>
70+
</div>
71+
<!-- /.post-container -->
72+
</main>
73+
</span>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import z from 'zod';
2+
3+
export const login_schema = z.object({
4+
email: z.string().email(),
5+
password: z.string()
6+
});

0 commit comments

Comments
 (0)