Skip to content

Commit 71b2c49

Browse files
authored
fix: submitters on remote forms (#14475)
* fix submitters on remote forms * use native FormData submitter parameter * tweak changeset * add tests * fix tests * aaa
1 parent 5f9df61 commit 71b2c49

File tree

15 files changed

+78
-30
lines changed

15 files changed

+78
-30
lines changed

.changeset/nine-months-start.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: include the value of form submitters on `form` remote functions

documentation/docs/20-core-concepts/30-form-actions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ We can also implement progressive enhancement ourselves, without `use:enhance`,
440440
/** @param {SubmitEvent & { currentTarget: EventTarget & HTMLFormElement}} event */
441441
async function handleSubmit(event) {
442442
event.preventDefault();
443-
const data = new FormData(event.currentTarget);
443+
const data = new FormData(event.currentTarget, event.submitter);
444444

445445
const response = await fetch(event.currentTarget.action, {
446446
method: 'POST',

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ For client-side validation, you can specify a _preflight_ schema which will popu
427427

428428
const schema = v.object({
429429
title: v.pipe(v.string(), v.nonEmpty()),
430-
content:v.pipe(v.string(), v.nonEmpty())
430+
content: v.pipe(v.string(), v.nonEmpty())
431431
});
432432
</script>
433433

packages/kit/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@
21992199

22002200
### Patch Changes
22012201

2202-
- fix: add `submitter` type to `SumbitFunction` ([#9484](https://github.com/sveltejs/kit/pull/9484))
2202+
- fix: add `submitter` type to `SubmitFunction` ([#9484](https://github.com/sveltejs/kit/pull/9484))
22032203

22042204
## 1.13.0
22052205

packages/kit/src/exports/public.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,11 @@ export type RemoteForm<Input extends RemoteFormInput | void, Output> = {
19371937
/** Preflight checks */
19381938
preflight(schema: StandardSchemaV1<Input, any>): RemoteForm<Input, Output>;
19391939
/** Validate the form contents programmatically */
1940-
validate(options?: { includeUntouched?: boolean }): Promise<void>;
1940+
validate(options?: {
1941+
includeUntouched?: boolean;
1942+
/** Perform validation as if the form was submitted by the given button. */
1943+
submitter?: HTMLButtonElement | HTMLInputElement;
1944+
}): Promise<void>;
19411945
/** The result of the form submission */
19421946
get result(): Output | undefined;
19431947
/** The number of pending submissions */

packages/kit/src/runtime/app/forms.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export function enhance(form_element, submit = () => {}) {
136136
? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formEnctype
137137
: clone(form_element).enctype;
138138

139-
const form_data = new FormData(form_element);
139+
const form_data = new FormData(form_element, event.submitter);
140140

141141
if (DEV && enctype !== 'multipart/form-data') {
142142
for (const value of form_data.values()) {
@@ -148,11 +148,6 @@ export function enhance(form_element, submit = () => {}) {
148148
}
149149
}
150150

151-
const submitter_name = event.submitter?.getAttribute('name');
152-
if (submitter_name) {
153-
form_data.append(submitter_name, event.submitter?.getAttribute('value') ?? '');
154-
}
155-
156151
const controller = new AbortController();
157152

158153
let cancelled = false;

packages/kit/src/runtime/client/client.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,12 +2543,7 @@ function _start_router() {
25432543
event.preventDefault();
25442544
event.stopPropagation();
25452545

2546-
const data = new FormData(event_form);
2547-
2548-
const submitter_name = submitter?.getAttribute('name');
2549-
if (submitter_name) {
2550-
data.append(submitter_name, submitter?.getAttribute('value') ?? '');
2551-
}
2546+
const data = new FormData(event_form, submitter);
25522547

25532548
// @ts-expect-error `URLSearchParams(fd)` is kosher, but typescript doesn't know that
25542549
url.search = new URLSearchParams(data).toString();

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ export function form(id) {
230230

231231
event.preventDefault();
232232

233-
const form_data = new FormData(form);
233+
const form_data = new FormData(form, event.submitter);
234234

235235
if (DEV) {
236236
validate_form_data(form_data, clone(form).enctype);
@@ -340,7 +340,7 @@ export function form(id) {
340340
event.stopPropagation();
341341
event.preventDefault();
342342

343-
const form_data = new FormData(form);
343+
const form_data = new FormData(form, target);
344344

345345
if (DEV) {
346346
const enctype = target.hasAttribute('formenctype')
@@ -350,10 +350,6 @@ export function form(id) {
350350
validate_form_data(form_data, enctype);
351351
}
352352

353-
if (target.name) {
354-
form_data.append(target.name, target?.getAttribute('value') ?? '');
355-
}
356-
357353
await handle_submit(form, form_data, callback);
358354
};
359355
};
@@ -422,12 +418,12 @@ export function form(id) {
422418
},
423419
validate: {
424420
/** @type {RemoteForm<any, any>['validate']} */
425-
value: async ({ includeUntouched = false } = {}) => {
421+
value: async ({ includeUntouched = false, submitter } = {}) => {
426422
if (!element) return;
427423

428424
const id = ++validate_id;
429425

430-
const form_data = new FormData(element);
426+
const form_data = new FormData(element, submitter);
431427

432428
/** @type {readonly StandardSchemaV1.Issue[]} */
433429
let array = [];

packages/kit/test/apps/basics/src/routes/remote/form/form.remote.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export const set_message = form(
1414
message: v.picklist(
1515
['hello', 'goodbye', 'unexpected error', 'expected error', 'redirect'],
1616
'message is invalid'
17-
)
17+
),
18+
uppercase: v.optional(v.string())
1819
}),
1920
async (data) => {
2021
if (data.message === 'unexpected error') {
@@ -29,7 +30,7 @@ export const set_message = form(
2930
redirect(303, '/remote');
3031
}
3132

32-
message = data.message;
33+
message = data.uppercase === 'true' ? data.message.toUpperCase() : data.message;
3334

3435
if (getRequestEvent().isRemoteRequest) {
3536
const deferred = Promise.withResolvers();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
import { my_form } from './form.remote.js';
3+
</script>
4+
5+
<form {...my_form}>
6+
<button name={my_form.field('submitter')} value="hello">submit</button>
7+
</form>
8+
9+
<p id="result">{my_form.result}</p>

0 commit comments

Comments
 (0)