Removing duplicate event listeners

14,447

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);
Share:
14,447
Peter
Author by

Peter

Updated on June 26, 2022

Comments

  • Peter
    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>