You want to do something with HTML elements on the page and like to use map and filter. But map and filter do not work because collections returned by querySelectorAll or getElementsByName are not arrays.
The console keeps telling you .map() or .filter() is not a function but you don't understand why.
I also did not understand why map and filter did not work and since I was in a hurry I almost reverted back to looping over the collection.
But there is an easy solution to this problem. After reading this article you know how to convert an HTMLCollection and NodeList to an array so you can use Map and Filter on it.
Let’s start by making a page with three buttons on it:
<button id="button1">Button1</button> <button id="button2">Button2</button> <button id="button3">Button3</button>
Suppose your application wants to disable all buttons on the page:
The first thing we need to do is query the document for all the buttons:
const htmlButtons = document.querySelectorAll('button'); console.log(htmlButtons);
Which will give you a NodeList with three items:
NodeList(3) [button#button1, button#button2, button#button3] 0: button#button1 1: button#button2 2: button#button3 length: 3
You can read more about a NodeList in the documentation but for this article all you need to know is that a NodeList is not an array and you cannot use map and filter on it.
If you try to use the NodeList as an array, you get an error. We can test this by mapping the items and disable each one:
htmlButtons.map(button => button.disabled = true);
Uncaught TypeError: t.map is not a function
Solution: Convert NodeList to an array
- The spread syntax that expands collections
How does that work?
const a = [1, 2]; console.log(a);
[ 1, 2 ]
const a = [1, 2]; b = [a, 3] console.log(b);
[ [ 1, 2 ], 3 ]
As expected, a new array has been created and contains two items, one is an array, one is a number. But if you want an array with all numbers (1, 2 and 3) flattened out, you can do this with the spread operator:
const a = [1, 2]; c = [...a, 3] console.log(c);
[ 1, 2, 3 ]
The spread operator unpacked the elements in array
a. You can use this functionality to unpack the elements in a NodeList or HTMLCollection and create an array from it.
Use the spread operator to create an array from a NodeList or HTMLCollection
Here is the full code that you need to:
- get all the buttons on the page
- convert the NodeList to an array
- map over the array to disable all buttons
const htmlButtons = document.querySelectorAll('button'); const htmlButtonsArray = [...htmlButtons]; htmlButtonsArray.map(button => button.disabled = true);
Free free to compact the code to a one-liner in your programs.
I hope this helps you with the HTML elements on your pages. From now, you can stop looping over HTML elements and start using the spread operator to manipulate the elements on the page like a pro!