Iteration
A loop repeats a piece of markup for every item of data. A café menu with twenty drinks does not need copying by hand — an array and one each are enough.
each over an array
A simple list of drinks in src/index.pug:
- const drinks = ["Espresso", "Cappuccino", "Hot chocolate"]
ul
each drink in drinks
li= drinkThe lines under each repeat for every item, and the drink variable takes the array values in turn:
<ul>
<li>Espresso</li>
<li>Cappuccino</li>
<li>Hot chocolate</li>
</ul>The item index
A second variable after a comma receives the item index, starting from zero:
- const drinks = ["Espresso", "Cappuccino", "Hot chocolate"]
each drink, index in drinks
p #{index + 1}. #{drink}To start numbering from one, add 1 to the index:
<p>1. Espresso</p>
<p>2. Cappuccino</p>
<p>3. Hot chocolate</p>A menu from data
In a real project the list comes from the build script. Pass an array of objects in build.js:
// build.js
const menu = [
{ name: "Espresso", price: 2 },
{ name: "Cappuccino", price: 3 },
{ name: "Hot chocolate", price: 3, soldOut: true },
];
const html = pug.renderFile("src/index.pug", { pretty: true, menu });In src/index.pug each item's properties are read with a dot, and a sold-out drink gets a class:
ul.menu
each item in menu
li(class=item.soldOut ? "sold-out" : undefined)
span.name= item.name
span.price $#{item.price}Three menu items; the hot chocolate has the sold-out class, which CSS can use to grey out the text:
<ul class="menu">
<li><span class="name">Espresso</span><span class="price">$2</span></li>
<li><span class="name">Cappuccino</span><span class="price">$3</span></li>
<li class="sold-out"><span class="name">Hot chocolate</span><span class="price">$3</span></li>
</ul>each over an object
When you loop over an object, the first variable receives the value and the second the key:
- const hours = { "Weekdays": "8:00–20:00", "Weekends": "10:00–18:00" }
dl
each time, days in hours
dt= days
dd= timeThe order of the variables is the reverse of what you might expect: value first, then key:
<dl>
<dt>Weekdays</dt>
<dd>8:00–20:00</dd>
<dt>Weekends</dt>
<dd>10:00–18:00</dd>
</dl>An empty list
An else branch under each is output when the array has no items:
- const desserts = []
ul
each dessert in desserts
li= dessert
else
li No desserts yet.Instead of an empty list the visitor sees a message:
<ul>
<li>No desserts yet.</li>
</ul>while
while repeats markup as long as a condition is true. You rarely need it — each is handier for lists:
- let n = 1
ul
while n <= 3
li Table #{n++}Remember to change the variable inside the loop (n++ here), otherwise the loop never ends:
<ul>
<li>Table 1</li>
<li>Table 2</li>
<li>Table 3</li>
</ul>Common mistake
Outputting the whole object instead of its property:
ul
each item in menu
li= itemJavaScript turns an object into the string [object Object]:
<ul>
<li>[object Object]</li>
<li>[object Object]</li>
<li>[object Object]</li>
</ul>Use the property you need: item.name, item.price.