Skip to content

Commit 784b66f

Browse files
committed
feat(forms): pass SubmitEvent to FormSubmitOptions.action
Allow submit action callbacks to access the SubmitEvent that triggered the form submission. This enables identifying the submitter button via event.submitter. Closes #67334
1 parent c90b6b3 commit 784b66f

File tree

4 files changed

+13
-5
lines changed

4 files changed

+13
-5
lines changed

MODULE.bazel.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/forms/signals/src/api/structure.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,14 +378,17 @@ export function applyWhenValue(
378378
export async function submit<TModel>(
379379
form: FieldTree<TModel>,
380380
options?: NoInfer<FormSubmitOptions<unknown, TModel>>,
381+
submitEvent?: SubmitEvent,
381382
): Promise<boolean>;
382383
export async function submit<TModel>(
383384
form: FieldTree<TModel>,
384385
action: NoInfer<FormSubmitOptions<unknown, TModel>['action']>,
386+
submitEvent?: SubmitEvent,
385387
): Promise<boolean>;
386388
export async function submit<TModel>(
387389
form: FieldTree<TModel>,
388390
options?: FormSubmitOptions<unknown, TModel> | FormSubmitOptions<unknown, TModel>['action'],
391+
submitEvent?: SubmitEvent,
389392
): Promise<boolean> {
390393
const node = untracked(form) as FieldState<unknown> as FieldNode;
391394

@@ -417,7 +420,7 @@ export async function submit<TModel>(
417420
try {
418421
if (shouldRun) {
419422
node.submitState.selfSubmitting.set(true);
420-
const errors = await untracked(() => action?.(field, detail));
423+
const errors = await untracked(() => action?.(field, detail, submitEvent));
421424
errors && setSubmissionErrors(node, errors);
422425
return !errors || (isArray(errors) && errors.length === 0);
423426
} else {

packages/forms/signals/src/api/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface FormSubmitOptions<TRootModel, TSubmittedModel> {
3434
action: (
3535
field: FieldTree<TRootModel & TSubmittedModel>,
3636
detail: {root: FieldTree<TRootModel>; submitted: FieldTree<TSubmittedModel>},
37+
submitEvent?: SubmitEvent,
3738
) => Promise<TreeValidationResult>;
3839
/**
3940
* Function to run when attempting to submit the form data but validation is failing.

packages/forms/signals/test/node/form_root.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,13 @@ describe('FormRoot', () => {
123123
})
124124
class TestCmp {
125125
submitted = false;
126+
submitterValue: string | null = null;
126127
readonly f = form(signal({}), {
127128
submission: {
128-
action: async () => {
129+
action: async (_field, _detail, event) => {
129130
this.submitted = true;
131+
const submitter = event?.submitter as HTMLButtonElement | null;
132+
this.submitterValue = submitter?.value ?? null;
130133
},
131134
},
132135
});
@@ -141,6 +144,7 @@ describe('FormRoot', () => {
141144

142145
expect(event.defaultPrevented).toBe(true);
143146
expect(component.submitted).toBeTrue();
147+
expect(component.submitterValue).toBe('submit');
144148
});
145149
});
146150

0 commit comments

Comments
 (0)