ngFor Done Right
July 04, 2019
When dealing with lists in templates, ngFor saves us a lot of time, but it could be a real pain if used wrong, read this article to know how to use it right.
Photo by Kolleen Gladden on Unsplash
All the information on this article can also be found in the official docs
Prerequisites
During this guide, we will use an interface that represents our lists’ object, let’s call it Item
, that’ll look something like this:
export interface Item {
_id: string
name: string
}
and we will use some utils
mock and functions that’ll help us later:
export const items: Item[] = [{ _id: "a2fHdS8P", name: "Mike" }]
export const makeRandomId = (): string => {
let result = ""
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
const charactersLength: number = characters.length
for (let i = 0; i < 8; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength))
}
return result
}
export const makeRandomName = (): string => {
const names = [
"Sara",
"Mattia",
...
]
return names[Math.floor(Math.random() * names.length)]
}
export const itemsLong: Item[] = [
{
_id: makeRandomId(),
name: makeRandomName(),
},
{
_id: makeRandomId(),
name: makeRandomName(),
},
...
]
First of all trackBy
trackBy
is a function that defines how to track changes for items in the iterable. That means we can use it to know exactly which element in a list is being changed, after a network call or whatsoever.
We implement it by defining a function in our .ts
file:
trackByFunction (index, item) {
return item._id;
}
then in your .html
add your new function
<div *ngFor="let item of items; trackBy: trackByFunction"></div>
Doing this lets your app be more performant as it doesn’t need to reload all of your view but only the element that’s being changed.
even and odd comes next
The variables even
and odd
are mainly used for styling the components.
For example, when we have a table and we want to make it more readable we can use these variables to change the background color of the rows.
In your html
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let item of items; trackBy: trackBy; odd as odd; even as even"
[ngClass]="{ 'odd': odd, 'even': even }"
>
<td>{{ item._id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
And in your css
/scss
file
.odd {
background-color: rgba(255, 0, 255, 0.45);
}
.even {
background-color: rgba(0, 0, 0, 0.45);
}
The result will be something like
Tell me about first and last
Just like even
and odd
, first
and last
variables are used for styling purposes too.
Let’s use the already created table and set the classes only for the first and last row:
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let item of items; trackBy: trackBy; first as first; last as last"
[ngClass]="{ 'first': first, 'last': last }"
>
<td>{{ item._id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
.first {
background-color: rgba(0, 0, 255, 0.45);
}
.last {
background-color: rgba(0, 255, 0, 0.45);
}
That’ll look like this
Don’t forget the index
The index
property does exactly what you think it does, it tells the index of the element in a list.
Maybe it’s the property that’s being used the most when we are dealing with lists, just think if you want to lay your lists’ element in defined rows using css
.
<mat-list>
<mat-list-item *ngFor="let item of items; trackBy: trackByFunction; index as index">{{ item.name }} index is {{ index }}</mat-list-item>
</mat-list>
All the code used in this guide can be found on Stackblitz and GitHub
Do you want to be updated when new articles are being published?
Join the newsletter! 😎