Stack Overflow Asked by prawn on December 22, 2021
I have a button. When this button is clicked I do two things
However, I cannot seem to be able to remove the eventlistener from the document on the close function. That is, the second time I try to open the menu, it immediately calls the close function
My question is…
How do I remove the document event listener?
And how do I make it so that if the user clicks the search menu, it does not trigger the document click event
openDesktopSearchMenu() {
this.$desktopSearchMenu.style.height = '330px';
document.addEventListener('click', this.closeDesktopSearchMenu.bind(this), true);
}
closeDesktopSearchMenu() {
this.$desktopSearchMenu.style.height = '0px';
document.removeEventListener('click', this.closeDesktopSearchMenu.bind(this), true);
}
Update July 24
Nick’s answer definitely put me in the right direction. However, the document was always being called first due to the capture parameter. So if the user clicks inside the search menu, it’s automatically closed.
Removing the capture parameter causes the close function to be invoked immediately after it opens.
The way around this that worked for me is to wrap the listener inside a timeout when I add it. And then naturally I had to call stopPropagation() on search menu click
searchMenuClick = (e) => {
e.stopPropagation();
}
/** open the desktop search menu */
openDesktopSearchMenu = () => {
this.$desktopSearchMenu.style.height = '330px';
this.$navBar.classList.add('search');
setTimeout(() => {
document.addEventListener('click', this.closeDesktopSearchMenu, { capture: false });
});
}
closeDesktopSearchMenu = () => {
this.$desktopSearchMenu.style.height = '0px';
setTimeout(() => {
this.$navBar.classList.remove('search');
}, 300);
document.removeEventListener('click', this.closeDesktopSearchMenu, { capture: false });
}
The .bind()
method returns a new function, so the function which you're adding as the callback to addEventListener
is a different reference to the one you're trying to remove. As a result, the event listener doesn't get removed.
You could consider binding in your constructor like so:
constructor() {
...
this.closeDesktopSearchMenu = this.closeDesktopSearchMenu.bind(this);
...
}
And then use your method like so (without the bind, as that's now done in the constructor):
openDesktopSearchMenu() {
this.$desktopSearchMenu.style.height = '330px';
document.addEventListener('click', this.closeDesktopSearchMenu, true);
}
closeDesktopSearchMenu() {
this.$desktopSearchMenu.style.height = '0px';
document.removeEventListener('click', this.closeDesktopSearchMen, true);
}
See example snippet below:
class Test {
constructor() {
this.prop = "bar";
this.foo = this.foo.bind(this);
}
foo() {
console.log('Foo', this.prop);
}
a() {
document.addEventListener('click', this.foo, true);
}
b() {
document.removeEventListener('click', this.foo, true);
}
}
const test = new Test();
console.log("Event listener added");
test.a();
setTimeout(() => {
console.log("Event listener removed");
test.b();
}, 3000);
Answered by Nick Parsons on December 22, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP