Reputation: 583
I have an event listener that is added by another event listener that is added by a function inside a class. I want this event listener to execute once and then remove itself.
To simplify the matter, let's assume I have the following HTML code :
<div class="container">
<div class="redDiv">some html</div>
<div class="blueDiv">some html</div>
</div>
and the following JavaScript code :
class Test {
constructor(_container){
this.container = _container;
}
somefunc(){
// some code here
this.removeEventListener('click',somefunc);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',somefunc);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
The first problem I came across, is that somefunc
is not defined at the scope of the second Event Listener. The only solution I have found was to create a new variable fnc
in the start
function and assign somefunc
to it and then call fnc
instead of somefunc
.
This made adding the event listener work and the code run as expected but then when somefunc()
was executed, removing the event listener didn't work because somefunc
was undefined at this scope.
I tried to pass somefunc
to this scope by changing the code to this :
class Test {
constructor(_container){
this.container = _container;
}
somefunc(func){
return function(){
// some code here
this.removeEventListener('click',func);
}
}
start(){
var fnc = this.somefunc;
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',fnc(fnc));
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
Now, the code doesn't generate any errors but the event listener isn't removed as desired. This has probably something to do with the way JavaScript assigns variables, a subject I don't really understand well. But what I'm interested in is how I can solve this matter and be able to remove the event listener once it is executed.
Upvotes: 0
Views: 612
Reputation: 6986
One solution is to use an arrow function to maintain the reference of this
...
class Test {
constructor(_container){
this.container = _container;
}
somefunc(fn){
console.log('clicked blue div')
this.container.querySelector('.blueDiv').removeEventListener('click', fn);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',() => {
console.log('clicked red div')
// Wrap someFunc in an arrow function to have "this" inside somefunc
// reference this class.
const func = () => this.somefunc(func);
container.querySelector('.blueDiv').addEventListener('click', func);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
Upvotes: 1