0

The problem lies in properly removing listeners from selectors in classes. When adding a listener, some arguments are passed to the function.

I tried to use .bind(this), but I don’t understand how it should work with functions that have arguments.

export default class Quiz {
    constructor() {
        this.selectElement = this.selectElement.bind(this);
        this.eventHandlers();
    }
    eventHandlers = () => {
        const listItem = document.querySelectorAll('.answer-menu__item');
    
        listItem.forEach((e, i) => {
            e.addEventListener('click', (elem) => this.selectElement(elem, i));
        });
    }
    selectElement = (element, index) => {
        // Doesn’t work.
        p.currentTarget.removeEventListener('click', this.selectElement);
    }
}
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
wowblvck
  • 41
  • 6
  • `removeEventListener` requires you to pass it the event listener you created, not an element. https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener eg. This would add a click event to the first div of a page, and then instantly remove. `const e = () => {/*nothing*/}; const el = document.querySelector('div'); el.addEventListener('click', e); el.removeEventListener('click', e);` – Keith Nov 15 '22 at 21:18
  • The function `this.selectElement` has never been added as an event listener to anything. Why do you expect removing it should work? Also, `bind` has no effect on arrow functions, other than passing arguments. Since arrow functions as class fields already bind `this` to the instance, the `.bind(this)` can just be removed. @Keith `this.selectElement` isn’t an Element, though. – Sebastian Simon Nov 15 '22 at 21:19
  • @SebastianSimon It doesn't matter what it is, because it has to be the same instance as `(elem) => {}` <---------- this.. IOW: I didn't even have to look a what a strangely named function `selectElement` does, I just know it's not the same instance he has added.. :) – Keith Nov 15 '22 at 21:23
  • 1
    Use [event delegation](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead of adding several event listeners — it’s more maintainable and applies to dynamically added elements. See [the tag info](/tags/event-delegation/info) and [this Q&A](/a/55452921/4642212). – Sebastian Simon Nov 15 '22 at 21:28
  • Okay guys. I like your answers, but I still can't figure out how to remove the event listener. Delegation is not suitable for me, because I need to pass the iteration number (i) to the function for further processing (I need to know which listitem the user clicked on in order 0, 1, 2... etc ). Just tell me how to use the addEventListener and removeEventListener functions in classes? – wowblvck Nov 16 '22 at 06:11
  • Instead of passing the number to the listener, why not [add a `data-*` attribute](//developer.mozilla.org/en/docs/Learn/HTML/Howto/Use_data_attributes) to the element, and then just read it in a delegated event listener? Otherwise, you’d have to maintain a [`WeakMap`](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) of Element → Function (the listener function that you can pass to `removeEventListener`). Alternatively, use event delegation and a `WeakMap` of Element → Number instead of `data-*` attributes. – Sebastian Simon Nov 16 '22 at 13:41
  • Okay thanks, that's what I did and also did the delegation. Thanks for the clarification, you helped me. – wowblvck Nov 16 '22 at 14:23

0 Answers0