I have a program that has a large number of reusable elements that all need an event listener. Because of this, I need a way to get the element from the listener. Here is what I want to do in code:
document.querySelectorAll(".class").forEach(function(el) {
el.addEventListener("click", function(element/*The element that the event listener is assigned to, passed as an argument*/) {
console.log(element) //Print out the element that was clicked in the console
})
})
Is there any way to replicate this or something of the sort in JavaScript?
I have a program that has a large number of reusable elements that all need an event listener. Because of this, I need a way to get the element from the listener. Here is what I want to do in code:
document.querySelectorAll(".class").forEach(function(el) {
el.addEventListener("click", function(element/*The element that the event listener is assigned to, passed as an argument*/) {
console.log(element) //Print out the element that was clicked in the console
})
})
Is there any way to replicate this or something of the sort in JavaScript?
Share Improve this question asked Jun 2, 2018 at 21:04 fin444fin444 7472 gold badges14 silver badges27 bronze badges 02 Answers
Reset to default 5You can access the clicked element with the this
keyword or your looping variable (el
) inside the event callback. this
is generally preferred because you won't have to worry about changing the code in the callback if your looping variable name changes and it avoids setting up a closure around el
, which (under the right circumstances) could have unintended side-effects.
But, also be aware the .querySelectorAll()
returns a "node list" and not an actual Array
and .forEach()
is an Array
method. Some browsers don't support calling .forEach()
on a node list, so you should convert that node list into a proper Array
for best patibility.
// Get the matching nodes in a node list and convert to an Array
let ary = Array.prototype.slice.call(document.querySelectorAll(".test"));
// Now, you can safely use .forEach()
ary.forEach(function(el) {
// Callbacks are passed a reference to the event object that triggered the handler
el.addEventListener("click", function(evt) {
// The this keyword will refer to the element that was clicked
console.log(this.id, el);
});
})
<div class="test" id="div1">Click me</div>
<p class="test" id="p1">No, click me</p>
<div class="test" id="div2">What about me?</div>
<h1 class="test" id="h1">Now, click me</h1>
In Javascript, you can reference variables in outer blocks/functions without having to pass them into inner functions:
document.querySelectorAll(".class").forEach(function(el) {
el.addEventListener("click", function(element) {
console.log(el);
})
});
If the element that triggers the click is the .class
itself (rather than one of .class
's descendants), you can also use event.target
to identify it:
document.querySelectorAll(".class").forEach(function(el) {
el.addEventListener("click", function(event) {
console.log(event.target);
})
});
If you have to pass the element as a parameter to a function for some reason rather than accessing the element in the outer scope, I suppose you could usebind
:
document.querySelectorAll(".class").forEach(function(el) {
el.addEventListener("click", logElement.bind(null, el));
});
function logElement(element) {
console.log(element);
}