Improve ngFor Performance Using Trackby In Angular
In this article, we will learn about how to improve ngFor performance in angular using Trackby. If the collection has a high number of items and is constantly changing, the Angular Trackby option enhances the performance of the ngFor. Learn why we need it and how to use it to boost the ngFor's performance.
Trackby in ngFor
We use ngFor to display inerrable items in a list or tabular format, such as an array. The following code, for example, iterates through the movie collection and displays each movie within a ul.
<ul> <li *ngFor="let movie of movies"> {{ movie.title }} - {{movie.director}} </li> </ul>
For each movie, Angular creates a li element. As a result, if there are n movies, angular will insert n li nodes into the DOM.
The facts, on the other hand, will not remain constant. From the back end, the user can add a new movie, delete an existing one, sort the list in a different order, or just refresh the movie. This will make angular render the template once more.
The simplest method to do this is to delete the entire list and re-render the DOM. However, this is inefficient, and it is a highly costly operation if the list is long.
To avoid this, Angular tracks the elements in the collection to the DOM nodes using the object identity. As a result, whether you add or remove an item, Angular will keep track of it and only update the DOM items that have changed.
However, if you reload the complete list from the back end, the objects in the movie collection will be replaced with the new objects. Even if the movies are identical, Angular will be unable to detect the change in object references. As a result, it treats them as new and renders them after deleting the old ones.
The following example demonstrate what occurs when the full list is refreshed. The app shows you a list of movies. It allows you to add a movie, remove a movie, and reload the whole thing.
Now, Open the app.component.ts and add the following code:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent implements OnInit { title: string = "Top 5 Movies"; movies=[]; mTitle:string=""; mDirector:string=""; ngOnInit() { this.Refresh(); } remove(i) { this.movies.splice(i,1); } addMovie() { this.movies.push({ title: this.mTitle, director: this.mDirector}) this.mTitle="" this.mDirector="" } Refresh() { console.log("refresh") this.movies = [ { title: 'Zootopia', director: 'Byron Howard, Rich Moore'}, { title: 'Batman v Superman: Dawn of Justice', director: 'Zack Snyder'}, { title: 'Captain American: Civil War', director: 'Anthony Russo, Joe Russo'}, { title: 'X-Men: Apocalypse', director: 'Bryan Singer'}, { title: 'Warcraft', director: 'Duncan Jones'}, ] } } class Movie { title: string; director: string; }
<h1> {{title}} </h1> <ul> <li *ngFor="let movie of movies; let i=index;trackBy: trackByFn;"> {{i}}. {{ movie.title }} - {{movie.director}} <button (click)="remove(i)">remove</button> </li> </ul> <button (click)="Refresh()">Refresh</button> <br> Title : <input type="text" [(ngModel)]="mTitle"> Director : <input type="text" [(ngModel)]="mDirector"> <button (click)="addMovie()">Add</button>
Now, run the application and see the output look's like below
As you can see in the sample above, Angular renders the full DOM each time we click refresh.
Trackby
We may overcome this issue by giving the trackBy option a function that returns a unique id for each item. To track the objects, the ngFor will use the unique id supplied by the trackBy function. As a result, even if the data is refreshed from the back end, the unique id remains the same, and the list is not presented a new.
The trackBy function takes two arguments: index and the currently selected item. It must return an id that identifies the item uniquely. The title is returned as the unique id in the following example.
trackByFn(index, item) { return item.title; }
<li *ngFor="let movie of movies; let i=index;trackBy: trackByFn;">
Now, run the application and see the changes like the below screen
Trackby multiple fields
You can also track many fields at the same time.
Now, Open the app.component.html and add the following code:
<li *ngFor="let movie of movies; let i=index;trackBy: trackByFnMultipleFields;">
trackByFnMultipleFields(index, item) { return item.title + item.director; }
Conclusion
In this article, we learned how to improve ngFor performance in angular using Trackby. In the next article, we will learn how to customize your angular apps in a variety of ways.
I hope this article helps you and you will like it.👍
If you have any doubt or confusion then free to ask in comment section.