Have you ever tried to add an event listener to a group of html elements all at once? if you had, you may had probably done something like this:
const buttons = document.getElementsByTagName("button");
buttons.forEach((item) => {
item.addEventListener("click", function () {
console.log("click");
});
});
The problem with the above code is that, when you finally check your browser console, you are going to encounter an error. Why?
This is because we are treating our list of buttons as an array while it is not.
It may look like an array, but it is actually either an htmlCollection or a nodeList. Whenever you make use of methods that fetch multiple elements/nodes from the DOM, that method either returns an htmlCollection or a nodeList.
Methods that returns an htmlCollection include: document.getElementsByClassName(), document.getElementsByTagName()
Methods that returns a nodeList include: document.querySelectorAll(), document.getElementsByName()
How to fix this Problem?
In order to fix this problem, all you need to do is convert the htmlCollection/nodeList into an array. This way you can make use of array methods on it, and also add your event listener.
You can use any method you prefer in order to convert the htmlCollection/nodeList into an array, but my favorite way of converting them into an array, is by making use of the spread operator.
Rewriting the above code using the spread operator will be:
const buttons = document.getElementsByTagName("button");
const buttonsArray = [...buttons];
buttonsArray.forEach((item) => {
item.addEventListener("click", function () {
console.log("click");
});
});
Now when you go to your browser console, everything will work as it is supposed to.
Top comments (5)
hmmm...
Yup, this.
HTMLCollection
is iterableIn case your elements have a common parent, it may be more efficient to set up an event listener on the parent and use event delegation.
Wouldn't just
[...buttons].forEach
be easier? Doesn't seem a great deal of point storing the array, unless you plan to use it again.That's true.
I only felt it will be easier to understand if the htmlCollection was separated from the array..