How to loop through selected elements with document.querySelectorAll
JavascriptHtmlJavascript Problem Overview
I am trying loop on selected elements that queried with document.querySelectorAll, but how?
For example I use:
var checkboxes = document.querySelectorAll('.check');
for( i in checkboxes) {
console.log(checkboxes[i]);
}
Output:
<input id="check-1" class="check" type="checkbox" name="check">
<input id="check-2" class="check" type="checkbox" name="check">
<input id="check-3" class="check" type="checkbox" name="check">
<input id="check-4" class="check" type="checkbox" name="check">
<input id="check-5" class="check" type="checkbox" name="check">
<input id="check-6" class="check" type="checkbox" name="check">
<input id="check-7" class="check" type="checkbox" name="check">
<input id="check-8" class="check" type="checkbox" name="check">
<input id="check-9" class="check" type="checkbox" name="check">
<input id="check-10" class="check" type="checkbox" name="check" checked="">
10
item()
namedItem()
My problem is that at the end this method returns 3 extra items. How can I properly do it?
Javascript Solutions
Solution 1 - Javascript
My favorite is using spread operator to convert it to array and then use forEach
for looping.
var div_list = document.querySelectorAll('div'); // returns NodeList
var div_array = [...div_list]; // converts NodeList to Array
div_array.forEach(div => {
// do something awesome with each div
});
I code in ES2015 and use Babel.js so there shouldn't be a browser support issue.
Solution 2 - Javascript
for in
loop is not recommended for arrays and array-like objects - you see why. There can be more than just number-indexed items, for example the length
property or some methods, but for in
will loop through all of them. Use either
for (var i = 0, len = checkboxes.length; i < len; i++) {
//work with checkboxes[i]
}
or
for (var i = 0, element; element = checkboxes[i]; i++) {
//work with element
}
The second way can't be used if some elements in array can be falsy (not your case), but can be more readable because you don't need to use []
notation everywhere.
Solution 3 - Javascript
It looks like Firefox 50+, Chrome 51+ and Safari 10+ now all support the .forEach
function for NodeList
objects. Note—.forEach
is not supported in Internet Explorer, so consider one of the approaches above or use a polyfill if IE support is required.
https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
const paragraphs = document.querySelectorAll('p');
paragraphs.forEach(p => console.log(p));
<p>paragraph 1</p>
<p>paragraph 2</p>
<p>paragraph 3</p>
<p>paragraph 4</p>
<p>paragraph 5</p>
Solution 4 - Javascript
With ES6, there is a static method Array.from
to take advantages of Array
non-static methods (map, filter, ...) :
Array.from(document.querySelectorAll('div')).forEach((element,index) =>
{
// handle "element"
});
Another use of Array.from
since querySelector
provides item
method:
var all = document.querySelectorAll('div');
// create range [0,1,2,....,all.length-1]
Array.from({length: all.length}, (v, k) => k).forEach((index) => {
let element = all.item(index);
});
Solution 5 - Javascript
A nice alternative is:
[].forEach.call(
document.querySelectorAll('.check'),
function (el) {
console.log(el);
}
);
but as pointed out, you should use a for loop.
Solution 6 - Javascript
A Main Takeaway:
The type matters.
.map
will not work directly on a NodeList
but will on an Array
.
Compare these:
Array.prototype.map()
NodeList.forEach()
Options:
ES6 available?
- The spread operator
[...element_list]
thenArray.map()
Array.from()
on aNodeList.forEach()
ES6 NOT available?
NodeList.forEach()
- A "
for
loop"
Solution 7 - Javascript
The shortest and cleanest way to be able to use any regular Array methods, or in your case a for in
loop on a NodeList
, is to spread it into an array as you fetch it:
const checkboxes = [...document.querySelectorAll('.check')];
for (i in checkboxes) {
console.log(checkboxes[i]);
}
Solution 8 - Javascript
U can select all elements using querySelectorAll
method. It will return an array of nodeList.
Lets say u want to select all p tags
<p>paragraph 1</p>
<p>paragraph 2</p>
<p>paragraph 3</p>
<p>paragraph 4</p>
<p>paragraph 5</p>
const paragraphs = document.querySelectorAll('p');
Now the paragraphs has a forEach method which can be used to loop through the nodelist
paragraphs.forEach(console.log); (logs node)
Solution 9 - Javascript
For me the most clean and accessible is for .. of
perfect syntax, second options for me is the three-dots
fi ES6 is available this is a good options as my personal opinion. Finally, forEach
if you are building big app and you want to provide support for most of the browsers out there this might give you some headaches.
const lis = document.querySelectorAll('li')
let results = {
'for': [],
'forEach': [],
'three-dots': [],
}
// ES6 bellow
for (const li of lis) {
results['for'].push(li)
}
// ES6 above
[...lis].forEach((li) => results['three-dots'].push(li))
// Most browsers support it
lis.forEach(li => results['forEach'].push(li))
console.log({results})
<u>
<li>Item 01</li>
<li>Item 02</li>
<li>Item 03</li>
<li>Item 04</li>
<li>Item 05</li>
<li>Item 06</li>
<li>Item 07</li>
<li>Item 08</li>
</u>