I have a website with multiple similar elements that need to have event listeners applied:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body>
<a href = '#' class = "click_me">Click me</a>
<br>
<a href = '#' class = "click_me">Click me</a>
<br>
<a href = '#' class = "click_me">Click me</a>
<script src = "example.js"></script>
<script>
new myClass(5);
</script>
</body>
</html>
I do this by looping over the elements. I want the callback function to have access to the element, the parent class instance and the event. So I think I have to define the callback function within the loop. However, this makes it difficult to remove the event listeners. In this example, I call the setUpEventHandlers
method twice, and the second call should remove the event listeners created by the first call. However, when I load the webpage, I can see both sets of listeners in the inspector. I think this is because the function is re-defined in the loop, so it is not treated as the same function by removeEventListener
. How can I remove the first set of listeners?
class myClass {
// Class constructor.
constructor(input_foo) {
// Process input.
this.foo = input_foo;
// Create event listeners for this instance.
this._setUpEventHandlers();
// Re-create event listeners (should remove previous ones).
this._setUpEventHandlers();
};
// Loops over elements and creates event listeners.
_setUpEventHandlers() {
// Loop over elements.
document.querySelectorAll('.click_me').forEach(element => {
// Define event listener function with "this" bound and
// appropriate signature.
var onClickFunction = function(event) {
this.onClick(element, event);
}.bind(this);
// Remove existing event listeners.
element.removeEventListener('click', onClickFunction, false);
// Add event listener function for this element.
element.addEventListener(
'click',
onClickFunction,
false
);
}
);
}
// Define event listener function.
onClick(element, event) {
event.preventDefault();
console.log(this);
console.log(event);
console.log(element);
console.log('<br>');
}
}
2
Answers
I adjusted your code so that it would work as you expect.
The reason why it wasn’t working for you is because a reference to the callback method handler is never saved. The same exact handler that is being used to instantiate a new event must be used to remove the event. In your case you were referencing an anonymous function that calls the event handler method, and you cannot re-refrence an anonymous function. Try using this:
In your code, the following line is creating a new anonymous function each time the _setUpEventHandlers method is called:
An arrow function can be used to avoid
bind
. You can also simplify your click handler invocation by accessingevent.currentTarget
instead of passing in a reference to the element. Therefore, you can do this: