Removing duplicate event listeners
Solution 1
In this example, we add and remove the listener in the same function as alternative to prevent redundant listeners.
function callbackFunction() {
console.log('Callback function was called.')
}
function addRemoveListener() {
let el = document.getElementById('btn-test')
el.removeEventListener('click', callbackFunction)
el.addEventListener('click', callbackFunction)
}
addRemoveListener()
addRemoveListener()
<button id="btn-test">Button</button>
Solution 2
When working with event listeners, I like to store them in an object so that I can keep track of what has been registered and easily remove them where necessary.
In your case, a simple boolean will do created in the global scope to check whether you need to remove the listener or not. (set to true after adding the listener).
<button id="myId">My Button</button>
<script>
var removeListener = false;
myFunction()
myFunction()
function myFunction() {
var el = document.getElementById('myId')
var listenerFn = function () {
console.log('My Message')
}
if (removeListener) el.removeEventListener('click', listenerFn)
el.addEventListener('click', listenerFn);
removeListener = true;
}
</script>
UPDATE As per your update, I have a revised answer. Its still not clear to me why you are calling the function twice, but we'll take that as a given.
<button id="myId">My Button</button>
<script>
var listeners = {};
myFunctionA();
myFunctionA();
function myFunctionA() {
var listenerFn1 = function() { //These functions need to be distinct so that we can refer to them when removing
console.log('My Message 1')
};
var listenerFn2 = function() { //We actually didn't need to move these out from where they were, but its a little easier to read this way
console.log('My Message 2')
};
function myFunctionB() {
if (el.innerHTML === 'My Button') {
if (listeners[el]) el.removeEventListener('click', listeners[el]);
el.addEventListener('click', listenerFn1);
listeners[el] = listenerFn1; //This could be expanded to account for different events, but keeping it simple for this scenario
}
else {
if (listeners[el]) el.removeEventListener('click', listeners[el]);
el.addEventListener('click', listenerFn2);
listeners[el] = listenerFn2;
}
}
var el = document.getElementById('myId');
myFunctionB();
}
</script>
The main point here is to have an object that stores the functions being called when the event is triggered. The object could allow for different events, e.g.:
var listener = {};
var el = document.getElementById('myId');
...
//Check if a click listener exists for el
if (listener[el] && listener[el].click) {
//Remove currently registered listener
el.removeEventListener('click', listener[el].click);
}
listener[el] = listener[el] || {}; //If listener[el] does not exist, create it
listener[el].click = function() {
//We can use an anonymous function in this case because we do not need to compare it to any other functions
console.log('Click 1');
};
el.addEventListener('click', listener[el].click);
If you want to allow multiple events to be attached to a listener, you cannot use anonymous functions as you want to make sure that you do not add the same function twice.
var listener = {};
var el = document.getElementById('myId');
...
var eventHandler1 = function() {
console.log('eventHandler1');
};
var eventHandler2 = function() {
console.log('eventHandler2');
};
//Check if a click listener exists for el that uses eventHandler1
if (listener[el] && listener[el].click && listener[el].click.includes(eventHandler1)) {
//Remove listener with eventHandler1
el.removeEventListener('click', listener[el].click.filter(function(val) {
return val === eventHandler1;
}));
}
listener[el] = listener[el] || {}; //If listener[el] does not exist, create it
listener[el].click = listener[el].click || [];
listener[el].click.push(eventHandler1);
el.addEventListener('click', eventHandler1);
Peter
Updated on June 26, 2022Comments
-
Peter almost 2 years
I have been trying to find a way to remove an event listener. I made a function that will add an event listener to a button but if the function runs again I want the event listener to be removed and added again. But instead it will just add another event listener and when I click on the button it will run the event listener function twice. Or even if I can just prevent it from adding a second event listener to the button would work too.
Here is the code
<button id="myId">My Button</button> <script> myFunction() myFunction() function myFunction() { var el = document.getElementById('myId') var listenerFn = function () { console.log('My Message') } el.removeEventListener('click', listenerFn) el.addEventListener('click', listenerFn) } </script>
Any tips would be most helpful.
UPDATE:
@FathiAlqadasi answer is the best so far for my issue. But I should of shown more of the code. the listener function is dynamic and can vary on what it does. Here is a another example of what I mean.
<button id="myId">My Button</button> <script> myFunctionA() myFunctionA() function myFunctionA() { var el = document.getElementById('myId') myFunctionB() function myFunctionB() { if (el.innerHTML === 'My Button') { var listenerFn = function () { console.log('My Message 1') } el.removeEventListener('click', listenerFn); el.addEventListener('click', listenerFn); } else { var listenerFn = function () { console.log('My Message 2') } el.removeEventListener('click', listenerFn); el.addEventListener('click', listenerFn); } } } </script>
UPDATE 2:
Thank you @ for the code. Here is the code in a neat codebox
<button id="myId">My Button</button> <script> var listenerFn; myFunction(); myFunction() function myFunction() { var el = document.getElementById('myId') el.removeEventListener('click', listenerFn); listenerFn = function() { console.log('My Message') } el.addEventListener('click', listenerFn, false); } </script>