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`
+
+ `);
+ 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`
+
+ `);
+ 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);