fix(form-core): dedupe click event label choice inputs
This commit is contained in:
parent
9aaf8959d5
commit
771147537a
4 changed files with 51 additions and 0 deletions
5
.changeset/eleven-pans-shave.md
Normal file
5
.changeset/eleven-pans-shave.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/form-core': patch
|
||||
---
|
||||
|
||||
Stop propagation of label click event in choice inputs to deduplicate the click event on the choice input.
|
||||
|
|
@ -128,6 +128,7 @@ const ChoiceInputMixinImplementation = superclass =>
|
|||
super();
|
||||
this.modelValue = { value: '', checked: false };
|
||||
this.disabled = false;
|
||||
this._preventDuplicateLabelClick = this._preventDuplicateLabelClick.bind(this);
|
||||
this.__toggleChecked = this.__toggleChecked.bind(this);
|
||||
}
|
||||
|
||||
|
|
@ -189,14 +190,37 @@ const ChoiceInputMixinImplementation = superclass =>
|
|||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (this._labelNode) {
|
||||
this._labelNode.addEventListener('click', this._preventDuplicateLabelClick);
|
||||
}
|
||||
this.addEventListener('user-input-changed', this.__toggleChecked);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (this._labelNode) {
|
||||
this._labelNode.removeEventListener('click', this._preventDuplicateLabelClick);
|
||||
}
|
||||
this.removeEventListener('user-input-changed', this.__toggleChecked);
|
||||
}
|
||||
|
||||
/**
|
||||
* The native platform fires an event for both the click on the label, and also
|
||||
* the redispatched click on the native input element.
|
||||
* This results in two click events arriving at the host, but we only want one.
|
||||
* This method prevents the duplicate click and ensures the correct isTrusted event
|
||||
* with the correct event.target arrives at the host.
|
||||
* @param {Event} ev
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
_preventDuplicateLabelClick(ev) {
|
||||
const __inputClickHandler = /** @param {Event} _ev */ _ev => {
|
||||
_ev.stopImmediatePropagation();
|
||||
this._inputNode.removeEventListener('click', __inputClickHandler);
|
||||
};
|
||||
this._inputNode.addEventListener('click', __inputClickHandler);
|
||||
}
|
||||
|
||||
__toggleChecked() {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -95,6 +95,26 @@ export function runChoiceInputMixinSuite({ tagString } = {}) {
|
|||
expect(counter).to.equal(1);
|
||||
});
|
||||
|
||||
it('fires one "click" event when clicking label or input, using the right target', async () => {
|
||||
const spy = sinon.spy();
|
||||
const el = /** @type {ChoiceInput} */ (await fixture(html`
|
||||
<${tag}
|
||||
@click="${spy}"
|
||||
>
|
||||
<input slot="input" />
|
||||
</${tag}>
|
||||
`));
|
||||
el.click();
|
||||
expect(spy.args[0][0].target).to.equal(el);
|
||||
expect(spy.callCount).to.equal(1);
|
||||
el._labelNode.click();
|
||||
expect(spy.args[1][0].target).to.equal(el._labelNode);
|
||||
expect(spy.callCount).to.equal(2);
|
||||
el._inputNode.click();
|
||||
expect(spy.args[2][0].target).to.equal(el._inputNode);
|
||||
expect(spy.callCount).to.equal(3);
|
||||
});
|
||||
|
||||
it('adds "isTriggerByUser" flag on model-value-changed', async () => {
|
||||
let isTriggeredByUser;
|
||||
const el = /** @type {ChoiceInput} */ (await fixture(html`
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ export declare class ChoiceInputHost {
|
|||
connectedCallback(): void;
|
||||
disconnectedCallback(): void;
|
||||
|
||||
_preventDuplicateLabelClick(ev: Event): void;
|
||||
|
||||
__toggleChecked(): void;
|
||||
|
||||
__syncModelCheckedToChecked(checked: boolean): void;
|
||||
|
|
|
|||
Loading…
Reference in a new issue