Telerik blogs
AngularT2_Light_1200x303

Today we will look at the trackBy directive and how to use it to improve the performance and speed of our apps.

When we build Angular apps, one of the most-used directives to show a list of items is ngFor, but do you know what happens when the data changes and how Angular works with the changes?

TrackBy is a directive that can work with ngFor to identify items in a list of DOM elements like a list or array to perform unique updates in the DOM, improving the speed and performance.

This post will look at why to use the trackBy directive in Angular and how it helps with application performance.

NgFor and Angular

When we need to render a list of items, the ngFor directive helps iterate over arrays or iterable objects and show them in the HTML template.

Let’s build a small example app that shows a list of colors to understand how it works. We have a default list with more than 600 colors with their hex codes as their unique IDs.

import { Component, VERSION } from '@angular/core';
import { COLORS } from './colors';

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})

export class AppComponent {
   colors = COLORS;
}

In our template, we use the ngFor directive to show the list of colors.

<ul>
<li *ngFor="let color of colors">
  {{ color.name }}
</li>
</ul>

What happened here? Nothing special, but Angular created one DOM node for each item in the array. What happens if we add a new color to our array? What happens with all the nodes?

Adding Colors

In our template, we add input and a button. The input uses #colorName to reference it, and the button uses the function addColor() to send the value of colorName input and push it to the array.

<div>
<input #colorName /><button (click)="addColor(colorName.value)">Add</button>
<ul>
 <li *ngFor="let color of colors">
   {{ color.name }}
 </li>
</ul>
</div>

Create the new method addColor with the parameter name in the TypeScript file. We create a new object newColor, and assign it to the colors array.

addColor(input: HTMLInputElement): void {
 if (!input.value) {
   return;
 }

 const newColor = { name: input.value, hex: Math.random().toString() };
 this.colors = [...this.colors, newColor];
 input.value = '';
}

The method adds the new color to the list; when the array changes, Angular needs to re-render all nodes in the DOM, and it is a heavy operation impacting our apps.

Because the ngFor directive doesn’t have a unique ID or key to know which element changed or modified, Angular needs to find how to detect the unique item in the array to commit safe DOM changes.

We want to update only the DOM element affected by the change with a unique ID that easily keeps the DOM UI state or selected item because the unique ID helps to track the specific item.

How can we tell Angular to trigger the change in the required item?

The TrackBy Directive

Angular came up with the trackBy directive, which is optionally passed into ngFor to help identify unique items in our arrays.

TrackBy and ngFor together allow Angular to detect the specific node element that needs to change or be added instead of rebuilding the whole array.

TrackBy expects a function to compare the items. It needs to be a pure function without side effects, return a unique value and be fast.

Using TrackBy With NgFor

First, we create a new function colorTrackBy that takes the color and returns the unique hex as ID.

colorTrackBy(index, color) {
 return color.hex;
}

Use trackBy and pass the colorTrackBy function as a parameter in our HTML.

<ul>
 <li *ngFor="let color of colors; trackBy: colorTrackBy">
   {{ color.name }}
 </li>
</ul>

Perfect! NgFor has a way to track the items, and Angular performs unique updates in our DOM!

If you want to see the final version of the code, feel free to play in https://stackblitz.com/edit/angular-ivy-hqboys?file=src%2Fapp%2Fapp.component.html.

Conclusion

We have seen how the trackBy directive works together with ngFor, why it is crucial when rendering an extensive list of elements without impacting the performance of our apps, and how to build our custom trackBy functions.


About the Author

Dany Paredes

Dany Paredes is a frontend developer who loves to share his experiences with Angular, TypeScript and Rxjs in his blog and on Twitter (@danywalls).

 

Related Posts

Comments

Comments are disabled in preview mode.