diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 6e4be38d6..0e5a124d3 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -6,6 +6,10 @@ Components with the Experimental bad _During the beta period, these restrictions may be relaxed in the event of a mission-critical bug._ 🐛 +## Next + +- Fixed a form submission bug + ## 2.0.0-beta.71 - 🚨 BREAKING: refactored exported parts to ensure composed components and their parts can be targeted via CSS diff --git a/src/components/button/button.test.ts b/src/components/button/button.test.ts index 63e2862e5..100d74f95 100644 --- a/src/components/button/button.test.ts +++ b/src/components/button/button.test.ts @@ -98,4 +98,92 @@ describe('', () => { expect(el.shadowRoot!.querySelector('button')).not.to.exist; }); }); + + describe('when submitting a form', () => { + it('should submit when the button is inside the form', async () => { + const form = await fixture(html` +
+ Submit +
+ `); + const button = form.querySelector('sl-button')!; + const handleSubmit = sinon.spy((event: SubmitEvent) => event.preventDefault()); + + form.addEventListener('submit', handleSubmit); + button.click(); + + expect(handleSubmit).to.have.been.calledOnce; + }); + + it('should submit when the button is outside the form and has a form attribute', async () => { + const el = await fixture(html` +
+
+ Submit +
+ `); + const form = el.querySelector('form')!; + const button = el.querySelector('sl-button')!; + const handleSubmit = sinon.spy((event: SubmitEvent) => event.preventDefault()); + + console.log(form, button); + + form.addEventListener('submit', handleSubmit); + button.click(); + + expect(handleSubmit).to.have.been.calledOnce; + }); + + it('should override form attributes when formaction, formmethod, formnovalidate, and formtarget are used inside a form', async () => { + const form = await fixture(html` +
+ + Submit + +
+ `); + const button = form.querySelector('sl-button')!; + const handleSubmit = sinon.spy((event: SubmitEvent) => { + submitter = event.submitter as HTMLButtonElement; + event.preventDefault(); + }); + let submitter!: HTMLButtonElement; + + form.addEventListener('submit', handleSubmit); + button.click(); + + expect(handleSubmit).to.have.been.calledOnce; + expect(submitter.formAction.endsWith('/bar')).to.be.true; + expect(submitter.formMethod).to.equal('get'); + expect(submitter.formTarget).to.equal('_blank'); + expect(submitter.formNoValidate).to.be.true; + }); + + it('should override form attributes when formaction, formmethod, formnovalidate, and formtarget are used outside a form', async () => { + const el = await fixture(html` +
+
+ + Submit + +
+ `); + const form = el.querySelector('form')!; + const button = el.querySelector('sl-button')!; + const handleSubmit = sinon.spy((event: SubmitEvent) => { + submitter = event.submitter as HTMLButtonElement; + event.preventDefault(); + }); + let submitter!: HTMLButtonElement; + + form.addEventListener('submit', handleSubmit); + button.click(); + + expect(handleSubmit).to.have.been.calledOnce; + expect(submitter.formAction.endsWith('/bar')).to.be.true; + expect(submitter.formMethod).to.equal('get'); + expect(submitter.formTarget).to.equal('_blank'); + expect(submitter.formNoValidate).to.be.true; + }); + }); }); diff --git a/src/internal/form-control.ts b/src/internal/form-control.ts index 638acad31..2490d5dd8 100644 --- a/src/internal/form-control.ts +++ b/src/internal/form-control.ts @@ -96,12 +96,13 @@ export class FormSubmitController implements ReactiveController { button.style.overflow = 'hidden'; button.style.whiteSpace = 'nowrap'; - // Pass form override properties through to the temporary button + // Pass form attributes through to the temporary button if (submitter) { - button.formAction = submitter.formAction; - button.formMethod = submitter.formMethod; - button.formNoValidate = submitter.formNoValidate; - button.formTarget = submitter.formTarget; + ['formaction', 'formmethod', 'formnovalidate', 'formtarget'].forEach(attr => { + if (submitter.hasAttribute(attr)) { + button.setAttribute(attr, submitter.getAttribute(attr)!); + } + }); } this.form.append(button);