From f23fac1465d7e0f6a6fa029f7395c91bd5b765c6 Mon Sep 17 00:00:00 2001 From: Elizabeth Mitchell Date: Fri, 18 Aug 2023 15:23:43 -0700 Subject: [PATCH] fix(button): add value to form when submitting Fixes #4526 PiperOrigin-RevId: 558261952 --- button/internal/button.ts | 16 +++++++++++++++ iconbutton/internal/icon-button.ts | 23 ++++++++++++++++++++++ internal/controller/form-submitter.ts | 18 ++++++++++++++++- internal/controller/form-submitter_test.ts | 23 +++++++++++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/button/internal/button.ts b/button/internal/button.ts index e9a176e022..bb7e2766ac 100644 --- a/button/internal/button.ts +++ b/button/internal/button.ts @@ -65,6 +65,22 @@ export abstract class Button extends LitElement implements FormSubmitter { @property() type: FormSubmitterType = 'submit'; + @property() value = ''; + + get name() { + return this.getAttribute('name') ?? ''; + } + set name(name: string) { + this.setAttribute('name', name); + } + + /** + * The associated form element with which this element's value will submit. + */ + get form() { + return this[internals].form; + } + @query('.button') private readonly buttonElement!: HTMLElement|null; @queryAssignedElements({slot: 'icon', flatten: true}) diff --git a/iconbutton/internal/icon-button.ts b/iconbutton/internal/icon-button.ts index 718ded6f8f..1204d6dd10 100644 --- a/iconbutton/internal/icon-button.ts +++ b/iconbutton/internal/icon-button.ts @@ -75,6 +75,29 @@ export class IconButton extends LitElement implements FormSubmitter { @property() type: FormSubmitterType = 'submit'; + @property() value = ''; + + get name() { + return this.getAttribute('name') ?? ''; + } + set name(name: string) { + this.setAttribute('name', name); + } + + /** + * The associated form element with which this element's value will submit. + */ + get form() { + return this[internals].form; + } + + /** + * The labels this element is associated with. + */ + get labels() { + return this[internals].labels; + } + @state() private flipIcon = isRtl(this, this.flipIconInRtl); /** @private */ diff --git a/internal/controller/form-submitter.ts b/internal/controller/form-submitter.ts index a2ff01bc3d..02cd4a460d 100644 --- a/internal/controller/form-submitter.ts +++ b/internal/controller/form-submitter.ts @@ -34,6 +34,20 @@ export interface FormSubmitter extends ReactiveElement, WithInternals { * - button: The element does nothing. */ type: FormSubmitterType; + + /** + * The HTML name to use in form submission. When combined with a `value`, the + * submitting button's name/value will be added to the form. + * + * Names must reflect to a `name` attribute for form integration. + */ + name: string; + + /** + * The value of the button. When combined with a `name`, the submitting + * button's name/value will be added to the form. + */ + value: string; } type FormSubmitterConstructor = @@ -71,7 +85,8 @@ export function setupFormSubmitter(ctor: FormSubmitterConstructor) { (ctor as unknown as typeof ReactiveElement).addInitializer(instance => { const submitter = instance as FormSubmitter; submitter.addEventListener('click', async event => { - const {type, [internals]: {form}} = submitter; + const {type, [internals]: elementInternals} = submitter; + const {form} = elementInternals; if (!form || type === 'button') { return; } @@ -102,6 +117,7 @@ export function setupFormSubmitter(ctor: FormSubmitterConstructor) { }); }, {capture: true, once: true}); + elementInternals.setFormValue(submitter.value); form.requestSubmit(); }); }); diff --git a/internal/controller/form-submitter_test.ts b/internal/controller/form-submitter_test.ts index d5d85e52b4..25f813ab9d 100644 --- a/internal/controller/form-submitter_test.ts +++ b/internal/controller/form-submitter_test.ts @@ -7,7 +7,7 @@ // import 'jasmine'; (google3-only) import {html, LitElement} from 'lit'; -import {customElement} from 'lit/decorators.js'; +import {customElement, property} from 'lit/decorators.js'; import {Environment} from '../../testing/environment.js'; import {Harness} from '../../testing/harness.js'; @@ -30,6 +30,8 @@ class FormSubmitterButton extends LitElement { static formAssociated = true; type: FormSubmitterType = 'submit'; + @property({reflect: true}) name = ''; + value = ''; [internals] = this.attachInternals(); } @@ -116,4 +118,23 @@ describe('setupFormSubmitter()', () => { .withContext('event.submitter') .toBe(harness.element); }); + + it('should add name/value to form data when present', async () => { + const {harness, form} = await setupTest(); + form.addEventListener('submit', event => { + event.preventDefault(); + }); + + harness.element.name = 'foo'; + harness.element.value = 'bar'; + + await harness.clickWithMouse(); + + const formData = Array.from(new FormData(form)); + expect(formData.length).withContext('formData.length').toBe(1); + + const [formName, formValue] = formData[0]; + expect(formName).toBe('foo'); + expect(formValue).toBe('bar'); + }); });