Looping With DOM Elements
Open the project folder
In our starter files, open the index.html page from this lessons folder:
04.Events-And-The-DOM > 08.Looping-with-dom-elements
Looping uses
When even creating a small number of elements using JavaScript things can get repetitive. Imaging creating a list with even five or ten items. We create the list item elements, then the content, then adding to a parent would be a lot of lines of code.
Or, if we wanted to add the same class to lots of elements, again it is a lot of work and repetition. To help with this we can use loops. Although we do have more on loops in a later section, we have already looked at some examples of looping in the arrays section. We used map
and forEach
to run a function for each item in the array.
This was a way of reducing repetition and this can also be applied to anything such as our DOM elements.
In the starter file, we can work with the header list items since there is more than one:
<ul class="nav-inline">
<li class="nav-item">our burgers</li>
<li class="nav-item">history</li>
</ul>
We can use loops to get all these list items, and make a change, such as adding a class, or removing them all.
First, grab all the list items with querySelectorAll
:
// ========= LOOPING =========
const listItems = document.querySelectorAll('li');
To add the classes manually, we would need to do something like this:
// ========= LOOPING =========
const listItems = document.querySelectorAll('li');
listItems[0].classList.add('inline');
Here we need to select each list item by the index number (listItems[0]
). If we had lots of elements to do this for, it would get repetitive, so instead we can use a loop.
The for of
loop
JavaScript has lots of types of loops available, but a relatively simple one we can use for this case is called for of
:
// ========= LOOPING =========
const listItems = document.querySelectorAll('li');
for (const item of listItems) {
// this loop will repeat for each item in listItems, which is twice:
item.classList.add('inline');
}
We can use const
here because the value of item never changes, it only selects one element at a time then moves onto the next one. This loops through our listItems
, and on each loop the current value is stored into the item
variable.
We can do anything to these selected elements, even remove
them if we want:
for (const item of listItems) {
item.classList.add('inline');
item.remove();
}
The forEach
loop
An alternative approach is to make use of a built-in method called forEach
(comment out for of
section).
Over to the console where we can see this. Type in listItems
in the console and expand the contents:
NodeList(2) [li.nav-item.inline, li.nav-item.inline]
0: li.nav-item.inline
1: li.nav-item.inline
length: 2
[[Prototype]]: NodeList
Expand the Prototype
which will reveal the forEach
method:
[[Prototype]]: NodeList
entries: ƒ entries()
forEach: ƒ forEach()
item: ƒ item()
keys: ƒ keys()
length: (...)
values: ƒ values()
constructor: ƒ NodeList()
Symbol(Symbol.iterator): ƒ values()
Symbol(Symbol.toStringTag): "NodeList"
get length: ƒ length()
[[Prototype]]: Object
Remember from an earlier lesson that we get back a NodeList
from querySelectorAll()
.
Inside the Prototype
, it inherits various properties and methods we can use, one of them is forEach
:
const listItems = document.querySelectorAll('li');
listItems.forEach(function (item) {
item.classList.add('inline');
});
Re-creating our example with JavaScript
This is how we can modify, but what about creating new elements, such as these full list items? Let’s try this out using the same methods vwe seen previously. Before we create new ones, comment out the old ones in the HTML:
<ul class="nav-inline">
<!-- <li class="nav-item">our burgers</li> -->
<!-- <li class="nav-item">history</li> -->
</ul>
First, comment out the previous examples and we can create a regular list item:
const listElement = document.createElement('li');
const listText = document.createTextNode('our burgers');
listElement.appendChild(listText);
listElement.classList.add('nav-item');
document.querySelector('ul').appendChild(listElement);
This will display one single list item in the browser. As we know, we would need to repeat these five lines to create item number two and so on.
Using the same for of
loop we can repeat this. We need the names of the list items (text content), which we can add to an array:
// 1. create links
const links = ['our burgers', 'history'];
// 2. then for of loop
for (const link of links) {
}
This loop will run twice, once for each item in our array. But what do we want to run? Well, we want to run the 5 lines of code from above (cut/paste contents into the loop body):
const links = ['our burgers', 'history'];
for (const link of links) {
const listElement = document.createElement('li');
const listText = document.createTextNode(link);
listElement.appendChild(listText);
listElement.classList.add('nav-item');
document.querySelector('ul').appendChild(listElement);
}
This will now display our two links in the browser header area. We have not saved a huge amount of code, but the benefits would be bigger if we had more than two list items to create.
Using forEach
with arrays
Alternatively, arrays also have a forEach
method, so we could use this too if we wanted:
links.forEach(function (link) {
// same 5 lines as inside for of loop:
const listElement = document.createElement('li');
const listText = document.createTextNode(link);
listElement.appendChild(listText);
listElement.classList.add('nav-item');
document.querySelector('ul').appendChild(listElement);
});
Loops are a great way to perform repetitive tasks in programming, and we will look at some more types of loops later.