Home > Net >  remove event listeners with extra arguments
remove event listeners with extra arguments

Time:09-21

Here is the event listener I'm using:

const eventHandler = (word, e) => {
    if(isAnimating && duplicates.includes(word.innerHTML)) return; 
    if(String.fromCharCode(e.which) == word.innerHTML && !distWords.includes(word)) {
        move(word);
    } 
}
words.forEach(word => {
    window.addEventListener("keypress", eventHandler.bind(null, word));
});  

The issue is I'm unable to remove the listener, I used something like this with no luck:

removeIT = () => {
        words.forEach(word => {
            window.removeEventListener("keypress", eventHandler.bind(null, word));
        }); 
}

How can I remove the listers effectivly?

CodePudding user response:

If you want to continue with this pattern you will need to store references to each bound function and iterate over them to remove the listeners.

const words_listeners = [];

words.forEach(word => {
    const handler = eventHandler.bind(null, word);
    window.addEventListener("keypress", handler);
    words_listeners.push(handler);
});  

removeIT = () => {
    words_listeners.forEach(handler => {
        window.removeEventListener("keypress", handler);
    }); 
}

The snippet below is attaching click listeners to buttons, so it is necessary to also store the element that the listener is attached to, but in your case, since you're attaching to the window, you won't need to. Basically, in the loop in which you are attaching the listeners, create your bound function and assign it to a variable, attach your listener with it, then push it to an array which can be used to remove the listeners later.

const buttons = document.querySelectorAll('.word')
const word_listeners = [];

const eventHandler = (word, e) => {
    console.log(word)
}

buttons.forEach(button => {
    const handler = eventHandler.bind(null, button.textContent);
    button.addEventListener('click', handler);
    word_listeners.push([button, handler]);
}); 

function remove_listeners() {
  word_listeners.forEach(([button, handler]) => button.removeEventListener('click', handler));
}

document.getElementById('remove').addEventListener('click', remove_listeners);
<button type="button" class="word">One</button>
<button type="button" class="word">Two</button>
<button type="button" class="word">Three</button>

<button type="button" id="remove">Remove listeners</button>

CodePudding user response:

I don't think it needs to be that complicated. If you call a function that returns a closure that acts the listener you don't need any binding.

I've had to use buttons here because I don't know what your markup is like.

const buttons = document.querySelectorAll('button');

function handleClick() {
  console.log(this);
}

function removeAllListeners(buttons) {
  buttons.forEach(button => {
    button.disabled = true;
    button.removeEventListener('click', handleClick);
  });
}

function handler(word) {
  console.log(word);
  return handleClick;
}

buttons.forEach(button => {
  const { textContent } = button;
  button.addEventListener('click', handler(textContent), false);
});

setTimeout(removeAllListeners, 5000, buttons);
button { background-color: #efefef; cursor: pointer; }
button:disabled { background-color: #ffb3b3; cursor: default; }
<button>Tree</button>
<button>Giant</button>
<button>Billy Joel</button>

  • Related