Skip to content

Commit 0904558

Browse files
committed
Better handling of redirect to same route edge case.
1 parent 567351f commit 0904558

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

src/lib/client/form.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { isElementInViewport, scrollToAndCenter } from './elements.js';
33
import type { FormOptions } from './index.js';
44
import { onDestroy, tick } from 'svelte';
55
import type { Writable } from 'svelte/store';
6-
import { afterNavigate } from '$app/navigation';
6+
import { afterNavigate, beforeNavigate } from '$app/navigation';
77

88
enum FetchStatus {
99
Idle = 0,
@@ -29,6 +29,7 @@ export function Form<T extends AnyZodObject, M>(
2929
) {
3030
let state: FetchStatus = FetchStatus.Idle;
3131
let delayedTimeout: number, timeoutTimeout: number;
32+
let aboutToNavigate = false;
3233

3334
//#region Timers
3435

@@ -179,25 +180,41 @@ export function Form<T extends AnyZodObject, M>(
179180
{
180181
ErrorTextEvents_addErrorTextListeners();
181182

182-
const completed = (cancelled: boolean) => {
183+
const completed = (cancelled: boolean, clearIfNotNavigating = false) => {
183184
Timers_clear();
184185
if (!cancelled) setTimeout(Form_scrollToFirstError);
186+
187+
// clearifNotNavigating is set when redirecting, to see if the navigation events
188+
// have been triggered. In rare cases they aren't, in which case we need to clear
189+
// the timers here, instead of in afterNavigate.
190+
if (clearIfNotNavigating && !aboutToNavigate) {
191+
Timers_clearAll();
192+
}
185193
};
186194

187195
onDestroy(() => {
188196
ErrorTextEvents_removeErrorTextListeners();
189197
completed(true);
190198
});
191199

200+
// If redirected, clear timers after navigating for better UX.
192201
if (!_initialized) {
202+
beforeNavigate((nav) => {
203+
if (nav.type == 'enter') return;
204+
aboutToNavigate = true;
205+
});
206+
193207
afterNavigate((nav) => {
194-
if (nav.type != 'enter') Timers_clearAll();
208+
if (nav.type == 'enter') return;
209+
aboutToNavigate = false;
210+
Timers_clearAll();
195211
});
196212
_initialized = true;
197213
}
198214

199215
return {
200216
submitting: () => {
217+
aboutToNavigate = false;
201218
Timers_start();
202219
},
203220

src/lib/client/formEnhance.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,10 @@ export function formEnhance<T extends AnyZodObject, M>(
490490
: document.location.origin
491491
).pathname == document.location.pathname
492492
) {
493-
htmlForm.completed(true);
493+
// Checks if beforeNavigate have been called in client/form.ts.
494+
setTimeout(() => {
495+
htmlForm.completed(true, true);
496+
}, 0);
494497
}
495498
}
496499

0 commit comments

Comments
 (0)