fix(form): sync submit and reset events instead of delegating

This commit is contained in:
gerjanvangeest 2019-08-05 14:01:27 +02:00 committed by Joren Broekema
parent 7ac9d88921
commit 5534369d45
2 changed files with 74 additions and 31 deletions

View file

@ -1,4 +1,3 @@
import { DelegateMixin } from '@lion/core';
import { LionFieldset } from '@lion/fieldset'; import { LionFieldset } from '@lion/fieldset';
/** /**
@ -8,50 +7,58 @@ import { LionFieldset } from '@lion/fieldset';
* @extends LionFieldset * @extends LionFieldset
*/ */
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
export class LionForm extends DelegateMixin(LionFieldset) { export class LionForm extends LionFieldset {
get delegations() {
return {
...super.delegations,
target: () => this.formElement,
events: [...super.delegations.events, 'submit', 'reset'],
methods: [...super.delegations.methods, 'submit', 'reset'],
};
}
constructor() {
super();
this.__boundSubmit = this._submit.bind(this);
this.__boundReset = this._reset.bind(this);
}
connectedCallback() { connectedCallback() {
super.connectedCallback(); if (super.connectedCallback) {
this.addEventListener('submit', this.__boundSubmit); super.connectedCallback();
this.addEventListener('reset', this.__boundReset); }
this.__registerEventsForLionForm();
} }
disconnectedCallback() { disconnectedCallback() {
super.disconnectedCallback(); if (super.disconnectedCallback) {
this.removeEventListener('submit', this.__boundSubmit); super.disconnectedCallback();
this.removeEventListener('reset', this.__boundReset); }
this.__teardownEventsForLionForm();
} }
get formElement() { get formElement() {
return this.querySelector('form'); return this.querySelector('form');
} }
submit() {
this.formElement.submit();
}
reset() {
this.formElement.reset();
}
/** /**
* As we use a native form there is no need for a role * As we use a native form there is no need for a role
*/ */
_setRole() {} // eslint-disable-line class-methods-use-this _setRole() {} // eslint-disable-line class-methods-use-this
_submit(ev) { __registerEventsForLionForm() {
ev.preventDefault(); this._submit = ev => {
this.submitGroup(); ev.preventDefault();
ev.stopPropagation();
this.dispatchEvent(new Event('submit', { bubbles: true }));
this.submitGroup();
};
this.formElement.addEventListener('submit', this._submit);
this._reset = ev => {
ev.preventDefault();
ev.stopPropagation();
this.dispatchEvent(new Event('reset', { bubbles: true }));
this.resetGroup();
};
this.formElement.addEventListener('reset', this._reset);
} }
_reset(ev) { __teardownEventsForLionForm() {
ev.preventDefault(); this.formElement.removeEventListener('submit', this._submit);
this.resetGroup(); this.formElement.removeEventListener('rest', this._reset);
} }
} }

View file

@ -1,4 +1,4 @@
import { expect, fixture, html } from '@open-wc/testing'; import { expect, fixture, html, oneEvent } from '@open-wc/testing';
import { spy } from 'sinon'; import { spy } from 'sinon';
import '@lion/input/lion-input.js'; import '@lion/input/lion-input.js';
@ -7,7 +7,7 @@ import '@lion/fieldset/lion-fieldset.js';
import '../lion-form.js'; import '../lion-form.js';
describe('<lion-form>', () => { describe('<lion-form>', () => {
it.skip('has a custom reset that gets triggered by native reset', async () => { it('has a custom reset that gets triggered by native reset', async () => {
const withDefaults = await fixture(html` const withDefaults = await fixture(html`
<lion-form <lion-form
><form> ><form>
@ -39,6 +39,24 @@ describe('<lion-form>', () => {
}); });
}); });
it('dispatches reset events', async () => {
const el = await fixture(html`
<lion-form>
<form>
<lion-input name="firstName" .modelValue="${'Foo'}"></lion-input>
</form>
</lion-form>
`);
setTimeout(() => el.reset());
const resetEv = await oneEvent(el, 'reset');
expect(resetEv).to.be.instanceOf(Event);
expect(resetEv.type).to.equal('reset');
expect(resetEv.target).to.equal(el);
expect(resetEv.bubbles).to.be.true;
expect(resetEv.composed).to.be.false;
});
it('works with the native submit event (triggered via a button)', async () => { it('works with the native submit event (triggered via a button)', async () => {
const submitSpy = spy(); const submitSpy = spy();
const el = await fixture(html` const el = await fixture(html`
@ -53,4 +71,22 @@ describe('<lion-form>', () => {
button.click(); button.click();
expect(submitSpy.callCount).to.equal(1); expect(submitSpy.callCount).to.equal(1);
}); });
it('dispatches submit events', async () => {
const el = await fixture(html`
<lion-form>
<form>
<button type="submit">submit</button>
</form>
</lion-form>
`);
const button = el.querySelector('button');
setTimeout(() => button.click());
const submitEv = await oneEvent(el, 'submit');
expect(submitEv).to.be.instanceOf(Event);
expect(submitEv.type).to.equal('submit');
expect(submitEv.target).to.equal(el);
expect(submitEv.bubbles).to.be.true;
expect(submitEv.composed).to.be.false;
});
}); });