diff --git a/.changeset/fluffy-lights-know.md b/.changeset/fluffy-lights-know.md new file mode 100644 index 000000000000..00e2e60767bf --- /dev/null +++ b/.changeset/fluffy-lights-know.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: `form.fields.set()` triggers `form.fields.value()` updates diff --git a/packages/kit/src/runtime/client/remote-functions/form.svelte.js b/packages/kit/src/runtime/client/remote-functions/form.svelte.js index 62c97b2f48d2..6d5d7b45fe4a 100644 --- a/packages/kit/src/runtime/client/remote-functions/form.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/form.svelte.js @@ -540,6 +540,15 @@ export function form(id) { } else { input = deep_set(input, path.map(String), value); } + + const copy = path.slice(); + + do { + const name = build_path_string(copy); + + versions[name] ??= 0; + versions[name] += 1; + } while (copy.pop() !== undefined); }, () => issues ) diff --git a/packages/kit/test/apps/basics/src/routes/remote/form/set/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/form/set/+page.svelte new file mode 100644 index 000000000000..f32a189d6740 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/form/set/+page.svelte @@ -0,0 +1,19 @@ + + +
{JSON.stringify(values.fields.value(), null, ' ')}
+
+
diff --git a/packages/kit/test/apps/basics/src/routes/remote/form/set/value.remote.ts b/packages/kit/test/apps/basics/src/routes/remote/form/set/value.remote.ts
new file mode 100644
index 000000000000..f6686abdc12b
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/remote/form/set/value.remote.ts
@@ -0,0 +1,11 @@
+import { form } from '$app/server';
+import * as v from 'valibot';
+
+export const values = form(
+ v.object({
+ leaf: v.string()
+ }),
+ async (data) => {
+ return { success: true, data };
+ }
+);
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index 1e64ded04982..0f44a98a3cc2 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -1982,6 +1982,26 @@ test.describe('remote functions', () => {
expect(JSON.parse(arrayValue)).toEqual([{ leaf: 'array-0-leaf' }, { leaf: 'array-1-leaf' }]);
});
+ test('form.fields.set() triggers form.fields.value() updates', async ({
+ page,
+ javaScriptEnabled
+ }) => {
+ if (!javaScriptEnabled) return;
+
+ await page.goto('/remote/form/set');
+
+ const before = await page.locator('#full-value').textContent();
+ expect(JSON.parse(before)).toEqual({});
+
+ await page.locator('#update-value').click();
+
+ const leafValue = await page.locator('input[name="leaf"]').inputValue();
+ expect(leafValue).toBe('new value');
+
+ const after = await page.locator('#full-value').textContent();
+ expect(JSON.parse(after)).toEqual({ leaf: 'new value' });
+ });
+
test('selects are not nuked when unrelated controls change', async ({
page,
javaScriptEnabled