fix(switch): dispatch checked-changed on checked change

This commit is contained in:
qa46hx 2020-09-24 13:38:07 +02:00 committed by Thomas Allmer
parent 175e6bea6f
commit 6aacbc4403
4 changed files with 83 additions and 12 deletions

View file

@ -51,12 +51,18 @@ export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField))
return html`${this._inputGroupTemplate()}`;
}
constructor() {
super();
this.role = 'switch';
this.checked = false;
this.__handleButtonSwitchCheckedChanged = this.__handleButtonSwitchCheckedChanged.bind(this);
}
connectedCallback() {
super.connectedCallback();
this._inputNode.addEventListener(
'checked-changed',
this.__handleButtonSwitchCheckedChanged.bind(this),
);
if (this._inputNode) {
this._inputNode.addEventListener('checked-changed', this.__handleButtonSwitchCheckedChanged);
}
if (this._labelNode) {
this._labelNode.addEventListener('click', this.__toggleChecked);
}
@ -65,6 +71,12 @@ export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField))
}
disconnectedCallback() {
if (this._inputNode) {
this._inputNode.removeEventListener(
'checked-changed',
this.__handleButtonSwitchCheckedChanged,
);
}
if (this._labelNode) {
this._labelNode.removeEventListener('click', this.__toggleChecked);
}
@ -86,7 +98,6 @@ export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField))
}
_syncButtonSwitch() {
this._inputNode.checked = this.checked;
this._inputNode.disabled = this.disabled;
}
}

View file

@ -74,29 +74,43 @@ export class LionSwitchButton extends DisabledWithTabIndexMixin(LitElement) {
super();
this.role = 'switch';
this.checked = false;
this.addEventListener('click', this.__handleToggleStateChange);
this.addEventListener('keydown', this.__handleKeydown);
this.addEventListener('keyup', this.__handleKeyup);
this.__toggleChecked = this.__toggleChecked.bind(this);
this.__handleKeydown = this.__handleKeydown.bind(this);
this.__handleKeyup = this.__handleKeyup.bind(this);
}
connectedCallback() {
super.connectedCallback();
this.setAttribute('aria-checked', `${this.checked}`);
this.addEventListener('click', this.__toggleChecked);
this.addEventListener('keydown', this.__handleKeydown);
this.addEventListener('keyup', this.__handleKeyup);
}
__handleToggleStateChange() {
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('click', this.__toggleChecked);
this.removeEventListener('keydown', this.__handleKeydown);
this.removeEventListener('keyup', this.__handleKeyup);
}
__toggleChecked() {
if (this.disabled) {
return;
}
// Force IE11 to focus the component.
this.focus();
this.checked = !this.checked;
}
__checkedStateChange() {
this.dispatchEvent(
new Event('checked-changed', {
composed: true,
bubbles: true,
}),
);
this.setAttribute('aria-checked', `${this.checked}`);
}
// eslint-disable-next-line class-methods-use-this
@ -109,7 +123,7 @@ export class LionSwitchButton extends DisabledWithTabIndexMixin(LitElement) {
__handleKeyup(e) {
if ([32 /* space */, 13 /* enter */].indexOf(e.keyCode) !== -1) {
this.__handleToggleStateChange();
this.__toggleChecked();
}
}
@ -126,8 +140,8 @@ export class LionSwitchButton extends DisabledWithTabIndexMixin(LitElement) {
*/
requestUpdateInternal(name, oldValue) {
super.requestUpdateInternal(name, oldValue);
if (this.isConnected && name === 'checked') {
this.setAttribute('aria-checked', `${this.checked}`);
if (this.isConnected && name === 'checked' && this.checked !== oldValue) {
this.__checkedStateChange();
}
}
}

View file

@ -73,6 +73,23 @@ describe('lion-switch-button', () => {
checkCall(handlerSpy.getCall(1), false);
});
it('should dispatch "checked-changed" event when checked changed', () => {
const handlerSpy = sinon.spy();
el.addEventListener('checked-changed', handlerSpy);
el.checked = true;
el.checked = false;
expect(handlerSpy.callCount).to.equal(2);
const checkCall = call => {
expect(call.args).to.have.a.lengthOf(1);
const e = call.args[0];
expect(e).to.be.an.instanceof(Event);
expect(e.bubbles).to.be.true;
expect(e.composed).to.be.true;
};
checkCall(handlerSpy.getCall(0), true);
checkCall(handlerSpy.getCall(1), false);
});
it('should not dispatch "checked-changed" event if disabled', () => {
const handlerSpy = sinon.spy();
el.disabled = true;

View file

@ -1,4 +1,5 @@
import { expect, fixture, html } from '@open-wc/testing';
import sinon from 'sinon';
import '../lion-switch.js';
describe('lion-switch', () => {
@ -68,6 +69,34 @@ describe('lion-switch', () => {
});
});
it('should dispatch "checked-changed" event when toggled via button or label', async () => {
const handlerSpy = sinon.spy();
const el = await fixture(html`<lion-switch .choiceValue=${'foo'}></lion-switch>`);
el.addEventListener('checked-changed', handlerSpy);
el._inputNode.click();
el._labelNode.click();
await el.updateComplete;
expect(handlerSpy.callCount).to.equal(2);
const checkCall = call => {
expect(call.args).to.have.a.lengthOf(1);
const e = call.args[0];
expect(e).to.be.an.instanceof(Event);
expect(e.bubbles).to.be.true;
expect(e.composed).to.be.true;
};
checkCall(handlerSpy.getCall(0), true);
checkCall(handlerSpy.getCall(1), false);
});
it('should dispatch "checked-changed" event when checked changed', async () => {
const handlerSpy = sinon.spy();
const el = await fixture(html`<lion-switch .choiceValue=${'foo'}></lion-switch>`);
el.addEventListener('checked-changed', handlerSpy);
el.checked = true;
await el.updateComplete;
expect(handlerSpy.callCount).to.equal(1);
});
it('is submitted by default', async () => {
const el = await fixture(html`<lion-switch></lion-switch>`);
expect(el.submitted).to.be.true;