In the lesson about conditional constructs, we used an object with data belonging to a user called Hexlet McCoderson:
const user = {
name: 'Hexlet',
surname: 'McCoderson',
login: 'hexlet-code',
}
We used object.key
when accessing the object fields. This is how we got data on the name and username of the user:
-
const user = {
name: 'Hexlet',
surname: 'McCoderson',
login: 'hexlet-code',
}
section.user-profile
p.name
if user.name && user.surname
| #{user.name} #{user.surname}
else
| #{user.login}
Let's modify the task a little bit and display the user in the learner rankings. We'll add the number of points and all the data to the table:
-
const user = {
name: 'Hexlet',
surname: 'McCoderson',
login: 'hexlet-code',
scores: 1271
}
section.container
h2 User rating
table
thead
tr
th Name
th Surname
th Login
th Scores
tbody
tr
td= user.name
td= user.surname
td= user.login
td= user.scores
This task is easy if you need to output a single user. But what if there are 2 users? 3? 100? There are two ways:
users
with all users inside it. Thus, each user will be allocated their own place in the array, making it convenient to add or delete users.Create a users
array and add several different users to it:
const users = [
{
name: 'Hexlet',
surname: 'McCoderson',
login: 'hexlet-code',
scores: 1271
},
{
name: 'Layout',
surname: 'ODesign',
login: 'king-of-layout',
scores: 1100
},
]
Special constructs, loops, are used to traverse such an array. Their task is to go through each element of the array and get the information inside it. Passing through the elements is called iteration. During the first iteration, you'll find Hexlet McCoderson's data. During the second iteration, you'll get Layout O'Design's data.
The main type of loop in Pug is the each in
. Essentially, it's for every “a” inside “b”. Where:
-
const users = [
{
name: 'Hexlet',
surname: 'McCoderson',
login: 'hexlet-code',
scores: 1271
},
{
name: 'Layout',
surname: 'ODesign',
login: 'king-of-layout',
scores: 1100
},
]
section.container
h2 User rating
table
thead
tr
th Name
th Surname
th Login
th Scores
tbody
each user in users
tr
td= user.name
td= user.surname
td= user.login
td= user.scores
<section class="container">
<h2>User rating</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Login</th>
<th>Scores</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hexlet</td>
<td>McCoderson</td>
<td>hexlet-code</td>
<td>1271</td>
</tr>
<tr>
<td>Layout</td>
<td>ODesign</td>
<td>king-of-layout</td>
<td>1100</td>
</tr>
</tbody>
</table>
</section>
The main change was the addition of just one line: each user in users
. We read it as follows: for each user in the users array and then output a tabular string with the data.
Important: you can assign any name to the variable that's accessible inside the loop. In the last example, this name may not be user
, it could be people
, or something else. Only you can choose that name, but try to choose a name that makes it clear what it represents. If the code inside the loop is large, it's the naming that determines how quickly and accurately the code will be interpreted by you or another developer.
You can read more in these articles:
You can't be sure that the array being searched has at least one element. If there are no elements, everything inside the array won't be output. At this point, it's important for the user to know that there's no information, so that they don't think there's an error with the page itself. This is what the each else
is for. This is similar to the conditional construct, but only works when the array is empty.
- const users = []
section.container
h2 User rating
table
thead
tr
th Name
th Surname
th Login
th Scores
tbody
each user in users
tr
td= user.name
td= user.surname
td= user.login
td= user.scores
else
tr
td(colspan='4') No users
<section class="container">
<h2>User rating</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Login</th>
<th>Scores</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4">No users</td>
</tr>
</tbody>
</table>
</section>
The code from the last example is equivalent to the following:
- const users = []
if users.length
each user in users
tr
td= user.name
td= user.surname
td= user.login
td= user.scores
else
tr
td(colspan='4') No users
When going through an object, you sometimes have to get not only the value, but also the key where the object is located. For example, users can be divided into different groups: users, moderators, administrators, and so on. In this case, the object may have the following form:
const users = {
admin: [
{
name: 'Hexlet',
surname: 'McCoderson',
},
],
moderator: [
{
name: 'Layout',
surname: 'ODesign',
},
{
name: 'Alex',
surname: 'Bossman',
},
],
}
The users users
has several keys: admin
and moderator
, whose values are arrays of users. A slightly modified each
loop syntax is used to output this list with job titles. In it, you need to get the key name and the array.
each people, position in users
h2= position
ul
each user in people
li= user.name + ' ' + user.surname
Several data are taken from the users
object: the people
variable gets the value, and the position
variable gets the key. Pay attention to the order of the variables: first the data and then the key.
This example uses a nested loop. This practice is standard for traversing big data. The first iteration in the top loop pulls the following data:
const people = [
{
name: 'Hexlet',
surname: 'McCoderson',
},
];
const position = 'admin';
The next step is to search through the people
array, which is done in the same way as in the example above.
<h2>admin</h2>
<ul>
<li>Hexlet McCoderson</li>
</ul>
<h2>moderator</h2>
<ul>
<li>Layout ODesign</li>
<li>Alex Bossman</li>
</ul>
The each
cycle is rightly considered the main one when working with Pug, but it isn't the only one. There are situations when it's necessary to repeat the same actions several times. In this case, each
doesn't help in any way, but in Pug there's another type of loop – while
. Its task is to repeat a section of code as long as the condition is true. For example,
- let count = 0;
ul
while count < 5
li= "Hello, my number is " + count
- count += 1;
<ul>
<li>Hello, my number is 0</li>
<li>Hello, my number is 1</li>
<li>Hello, my number is 2</li>
<li>Hello, my number is 3</li>
<li>Hello, my number is 4</li>
</ul>
When using the while
, it's important to make sure that the condition changes to false sooner or later. This is a common mistake that can lead to an endless loop. In the last example, to get an infinite loop, all you need to do is count += 1;
. Without it, the value of count
will always be zero, which means that the condition count < 5
will be true at any point during compilation.
The following kind of array goes into icon.pug:
-
const icons = {
free: [
{
name: 'robot',
url: './icons/robot.svg'
},
{
name: 'hexlet',
url: './icons/hexlet.svg'
}
],
premium: [
{
name: 'cat',
url: './icons/premium/cat.svg'
},
{
name: 'dog',
url: './icons/premium/dog.svg'
}
]
};
Convert the data into the following template:
<h2>free</h2>
<ul>
<li><a href="./icons/robot.svg">robot</a></li>
<li><a href="./icons/hexlet.svg">hexlet</a></li>
</ul>
<h2>premium</h2>
<ul>
<li><a href="./icons/premium/cat.svg">cat</a></li>
<li><a href="./icons/premium/dog.svg">dog</a></li>
</ul>
The Hexlet support team or other students will answer you.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.
Programming courses for beginners and experienced developers. Start training for free
Our graduates work in companies:
Sign up or sign in
Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.