From 744dc81c6b0d8cade087df733c6d3d3f1281e68c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 2 Mar 2023 14:52:55 -0500 Subject: [PATCH] set `form` to `null` before updating it with real values (#9267) * set `form` to `null` before updating it with real values - fixes #8513 * changeset and test --- .changeset/thin-readers-speak.md | 5 +++++ packages/kit/src/runtime/client/client.js | 15 ++++++++++----- .../routes/actions/enhance/+page.server.js | 7 +++++++ .../src/routes/actions/enhance/+page.svelte | 13 ++++++++++--- packages/kit/test/apps/basics/test/test.js | 19 +++++++++++++++++-- 5 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 .changeset/thin-readers-speak.md diff --git a/.changeset/thin-readers-speak.md b/.changeset/thin-readers-speak.md new file mode 100644 index 000000000000..6e2146a5bf86 --- /dev/null +++ b/.changeset/thin-readers-speak.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: preserve form state when submitting a second time diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 5795105dbc0d..11f83e40b56d 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1410,14 +1410,19 @@ export function create_client(app, target) { goto(result.location, { invalidateAll: true }, []); } else { /** @type {Record} */ - const props = { - form: result.data, + root.$set({ + // this brings Svelte's view of the world in line with SvelteKit's + // after use:enhance reset the form.... + form: null, page: { ...page, form: result.data, status: result.status } - }; - root.$set(props); + }); + + // ...so that setting the `form` prop takes effect and isn't ignored + await tick(); + root.$set({ form: result.data }); if (result.type === 'success') { - tick().then(reset_focus); + reset_focus(); } } }, diff --git a/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.server.js b/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.server.js index da8b3975d012..db3fe786c516 100644 --- a/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.server.js +++ b/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.server.js @@ -32,5 +32,12 @@ export const actions = { }, error: () => { throw error(400, 'error'); + }, + echo: async ({ request }) => { + const data = await request.formData(); + + return { + message: data.get('message') + }; } }; diff --git a/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.svelte b/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.svelte index e3b46da4bc1c..5c63d42a5e66 100644 --- a/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/actions/enhance/+page.svelte @@ -14,12 +14,14 @@
{JSON.stringify($page.form)}
- - + + - +
@@ -35,3 +37,8 @@ > + +
+ + +
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index 91d8a4e595c8..3e242b9e73d9 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -976,7 +976,7 @@ test.describe('Actions', () => { } }); - test('use:enhance button with formAction', async ({ page, app }) => { + test('use:enhance button with formAction', async ({ page }) => { await page.goto('/actions/enhance'); expect(await page.textContent('pre.formdata1')).toBe(JSON.stringify(null)); @@ -989,7 +989,7 @@ test.describe('Actions', () => { ); }); - test('use:enhance button with name', async ({ page, app }) => { + test('use:enhance button with name', async ({ page }) => { await page.goto('/actions/enhance'); expect(await page.textContent('pre.formdata1')).toBe(JSON.stringify(null)); @@ -1004,6 +1004,21 @@ test.describe('Actions', () => { ); }); + test('use:enhance does not clear form on second submit', async ({ page }) => { + await page.goto('/actions/enhance'); + + await page.locator('input[name="message"]').fill('hello'); + + await page.locator('.form3').click(); + await expect(page.locator('pre.formdata1')).toHaveText(JSON.stringify({ message: 'hello' })); + await expect(page.locator('pre.formdata2')).toHaveText(JSON.stringify({ message: 'hello' })); + + await page.locator('.form3').click(); + await page.waitForTimeout(0); // wait for next tick + await expect(page.locator('pre.formdata1')).toHaveText(JSON.stringify({ message: 'hello' })); + await expect(page.locator('pre.formdata2')).toHaveText(JSON.stringify({ message: 'hello' })); + }); + test('redirect', async ({ page, javaScriptEnabled }) => { await page.goto('/actions/redirect');