Skip to content

Commit 0bd9942

Browse files
authored
fix: don't reset form after enhanced form submit (#14626)
* WIP don't reset form after enhanced form submit * fix test * changeset * docs
1 parent be1020d commit 0bd9942

File tree

4 files changed

+42
-10
lines changed

4 files changed

+42
-10
lines changed

.changeset/heavy-donkeys-attack.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: don't automatically reset form after an enhanced submission

documentation/docs/20-core-concepts/60-remote-functions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,8 @@ We can customize what happens when the form is submitted with the `enhance` meth
757757
</form>
758758
```
759759
760+
> When using `enhance`, the `<form>` is not automatically reset — you must call `form.reset()` if you want to clear the inputs.
761+
760762
The callback receives the `form` element, the `data` it contains, and a `submit` function.
761763
762764
To enable client-driven [single-flight mutations](#form-Single-flight-mutations), use `submit().updates(...)`. For example, if the `getPosts()` query was used on this page, we could refresh it like so:

packages/kit/src/runtime/client/remote-functions/form.svelte.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ export function form(id) {
7171
*/
7272
const versions = $state({});
7373

74+
/**
75+
* This ensures that `{field.value()}` is updated even if the version hasn't been initialized
76+
* @type {Set<string>}
77+
*/
78+
const version_reads = new Set();
79+
7480
/** @type {Record<string, InternalRemoteFormIssue[]>} */
7581
let issues = $state.raw({});
7682

@@ -91,6 +97,16 @@ export function form(id) {
9197

9298
let submitted = false;
9399

100+
function update_all_versions() {
101+
for (const path of version_reads) {
102+
versions[path] ??= 0;
103+
}
104+
105+
for (const key of Object.keys(versions)) {
106+
versions[key] += 1;
107+
}
108+
}
109+
94110
/**
95111
* @param {FormData} form_data
96112
* @returns {Record<string, any>}
@@ -219,14 +235,7 @@ export function form(id) {
219235
if (issues.$) {
220236
release_overrides(updates);
221237
} else {
222-
input = {};
223-
224-
for (const [key, value] of Object.entries(versions)) {
225-
if (value !== undefined) {
226-
versions[key] ??= 0;
227-
versions[key] += 1;
228-
}
229-
}
238+
update_all_versions();
230239

231240
if (form_result.refreshes) {
232241
refresh_queries(form_result.refreshes, updates);
@@ -420,6 +429,15 @@ export function form(id) {
420429
}
421430
});
422431

432+
form.addEventListener('reset', async () => {
433+
// need to wait a moment, because the `reset` event occurs before
434+
// the inputs are actually updated (so that it can be cancelled)
435+
await tick();
436+
437+
input = convert_formdata(new FormData(form));
438+
update_all_versions();
439+
});
440+
423441
return () => {
424442
element = null;
425443
preflight_schema = undefined;
@@ -510,7 +528,10 @@ export function form(id) {
510528
create_field_proxy(
511529
{},
512530
() => input,
513-
(path) => versions[path],
531+
(path) => {
532+
version_reads.add(path);
533+
versions[path];
534+
},
514535
(path, value) => {
515536
if (path.length === 0) {
516537
input = value;

packages/kit/test/apps/basics/test/test.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,12 +1806,16 @@ test.describe('remote functions', () => {
18061806
await page.getByText('resolve deferreds').click();
18071807
await expect(page.getByText('enhanced.pending:')).toHaveText('enhanced.pending: 0');
18081808
await expect(page.getByText('await get_message():')).toHaveText('await get_message(): hello');
1809+
1810+
// enhanced submission should not clear the input; the developer must do that at the appropriate time
1811+
await expect(page.locator('[data-enhanced] input')).toHaveValue('hello');
1812+
} else {
1813+
await expect(page.locator('[data-enhanced] input')).toHaveValue('');
18091814
}
18101815

18111816
await expect(page.getByText('enhanced.result')).toHaveText(
18121817
'enhanced.result: hello (from: enhanced)'
18131818
);
1814-
await expect(page.locator('[data-enhanced] input')).toHaveValue('');
18151819
});
18161820

18171821
test('form preflight works', async ({ page, javaScriptEnabled }) => {

0 commit comments

Comments
 (0)