Reputation: 2548
This question has been asked before. In fact, it's been asked with nearly the same title but please stick with me for a moment, I don't think the question has a good answer yet.
So, we have an event listener:
fancyButton.addEventListener('click', this.launchKitty, true);
And then we have a function:
// assume this.setForLaunch was set somewhere
launchKitty = () => {
if(this.setForLaunch){ // behold, this!
console.log('farewell, feline!')
}
}
We have an event listener and a function with access to the outer this
, which is neat. Removal is easy:
fancyButton.removeEventListener('click', this.launchKitty, true);
But what if we didn't want to use this
?
What if, instead of leaning on this
, we wanted to pass addEventListener
an argument? Like so:
fancyButton.addEventListener('click', () => {this.launchKitty(true)}, true);
And a slightly modified launchKitty()
:
launchKitty(setForLaunch) {
if(setForLaunch){ // now we're using a parameter!
console.log('farewell, feline!')
}
}
So far, so good. Kitties are launched. What about removing the listener?
fancyButton.removeEventListener('click', () => {this.launchKitty}, true);
Not going to work. Our () => {}
is anonymous and therefore removeEventListener
doesn't know how to find it.
How can we pass an event listener a parameter and then later remove said event handler?
Please feel free to challenge any of my assumptions. There are a lot of ways to launch this cat.
Thanks!
Upvotes: 2
Views: 1649
Reputation: 5837
Alternatively to @CertainPerformance's answer. You can use the bind method from the Function prototype to instantiate a 'copy' of the function with parameters bound to it.
Something like:
function launchKitty(setForLaunch) {
console.log(`launchKitty called with setForLaunch = ${setForLaunch}`);
}
let fancyTrue = launchKitty.bind(null, true);
let fancyFalse = launchKitty.bind(null, false);
let fancyButton = document.getElementById('fancyButton');
let lessFancyButton = document.getElementById('lessFancyButton');
let detachButton = document.getElementById('detachFancyButton');
fancyButton.addEventListener('click', fancyTrue, true);
lessFancyButton.addEventListener('click', fancyFalse, true);
detachButton.addEventListener('click', () => {
fancyButton.removeEventListener('click', fancyTrue, true);
lessFancyButton.removeEventListener('click', fancyFalse, true);
});
<button id='fancyButton'>Console Log</button>
<button id='lessFancyButton'>No Console Log</button>
<button id='detachFancyButton'>Detach Handlers</button>
Upvotes: 1
Reputation: 370699
You should store the currently anonymous function into a variable, so that you can call removeEventListener
with it later:
const launchKittyTrue = () => { this.launchKitty(true) };
fancyButton.addEventListener('click', launchKittyTrue, true);
// later:
fancyButton.removeEventListener('click', launchKittyTrue, true);
To be more flexible, you might consider a Map
indexed by arguments, whose values are the bound functions:
const boundFns = new Map();
function makeListener(arg) {
if (!boundFns.has(arg)) {
boundFns.set(arg, launchKitty.bind(undefined, arg));
}
return boundFns.get(arg);
}
function getListener(arg) {
return boundFns.get(arg);
}
fancyButton.addEventListener('click', makeListener(true), true);
// later:
fancyButton.removeEventListener('click', getListener(true), true);
Upvotes: 4