Remove document and window event handlers when removing custom elements
I realized that the event handlers that i was setting when creating the tags input and the multi-select controls were not removed just because these elements are no longer in the document, and kept firing again and again. I no longer can use an anonymous function, because removeEventListener would not match it with the one passed to addEventListener. I also have to bind the handler to `this` in order to keep having access to the object, and, again, can not do it in the call to addEventListener, or i would get a different function each time. I added the check to see if the element is connected inside the connectedCallback because the documentation warns that this callback “may be called once your element is no longer connected”[0], and i understood it to mean that the connected and disconnected callbacks could be called our of order, thus it would be possible to add event listeners that would not be removed—again. I am not actually sure where i have to do the same for the rest of the “internal” events. [0]: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks
This commit is contained in:
parent
ba880c6560
commit
f945051f4a
|
@ -4,9 +4,13 @@ class Multiselect extends HTMLDivElement {
|
|||
this.initialized = false;
|
||||
this.toSearch = '';
|
||||
this.highlighted = 0;
|
||||
this.onFocusOutHandler = this.onFocusOut.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.isConnected) {
|
||||
return;
|
||||
}
|
||||
if (!this.initialized) {
|
||||
for (const child of this.children) {
|
||||
switch (child.nodeName) {
|
||||
|
@ -22,6 +26,19 @@ class Multiselect extends HTMLDivElement {
|
|||
this.init();
|
||||
}
|
||||
}
|
||||
window.addEventListener('focusin', this.onFocusOutHandler);
|
||||
document.addEventListener('click', this.onFocusOutHandler);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
document.removeEventListener('click', this.onFocusOutHandler);
|
||||
window.removeEventListener('focusin', this.onFocusOutHandler);
|
||||
}
|
||||
|
||||
onFocusOut(e) {
|
||||
if (this.contains(e.target)) return;
|
||||
if (!e.target.isConnected) return;
|
||||
this.close();
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -93,17 +110,6 @@ class Multiselect extends HTMLDivElement {
|
|||
this.options.setAttribute('role', 'listbox');
|
||||
this.close();
|
||||
|
||||
window.addEventListener('focusin', (e) => {
|
||||
if (this.contains(e.target)) return;
|
||||
this.close();
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (this.contains(e.target)) return;
|
||||
if (!e.target.isConnected) return;
|
||||
this.close();
|
||||
});
|
||||
|
||||
this.rebuild();
|
||||
}
|
||||
|
||||
|
@ -278,9 +284,13 @@ class Tags extends HTMLDivElement {
|
|||
super();
|
||||
this.initialized = false;
|
||||
this.tags = [];
|
||||
this.onFocusOutHandler = this.onFocusOut.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.isConnected) {
|
||||
return;
|
||||
}
|
||||
if (!this.initialized) {
|
||||
for (const child of this.children) {
|
||||
switch (child.nodeName) {
|
||||
|
@ -296,6 +306,18 @@ class Tags extends HTMLDivElement {
|
|||
this.init();
|
||||
}
|
||||
}
|
||||
window.addEventListener('focusin', this.onFocusOutHandler);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
window.removeEventListener('focusin', this.onFocusOutHandler);
|
||||
}
|
||||
|
||||
onFocusOut(e) {
|
||||
if (this.contains(e.target)) return;
|
||||
if (e.target.value && e.target.value.trim() !== '') {
|
||||
this.createTag();
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -339,12 +361,6 @@ class Tags extends HTMLDivElement {
|
|||
break;
|
||||
}
|
||||
});
|
||||
window.addEventListener('focusin', (e) => {
|
||||
if (this.contains(e.target)) return;
|
||||
if (e.target.value.trim() !== '') {
|
||||
this.createTag();
|
||||
}
|
||||
});
|
||||
|
||||
// Must come after the search input
|
||||
this.tagList.append(this.label);
|
||||
|
|
Loading…
Reference in New Issue