TrackBy With ngFor Directives in Angular Application
Hello Readers,
In this post, we are going to see a very interesting thing and i.e. trackyBy with ngFor directive!
Why use trackyBy with ngFor directive :
- ngFor directive may perform poorly with large lists.
- A small change to the list like, adding a new item or removing an existing item may trigger several DOM manipulations.
Let’s look at an example, suppose we are having an “Employee Component” in the project.
Now consider this below code in employee.component.ts file.
Note:
- The constructor() initializes the “employees” property with 4 employee objects.
- getEmployees() method returns another list of 5 employee objects (The 4 existing employees plus a new employee object)
Now look at this code in employee.component.html
Ok now let’s check what we are exactly doing. At the moment we are not using trackBy with ngFor directive. So what above code will do is that:
- When the page initially loads we see the 4 employees.
- When we click “Refresh Employees” button we see the fifth employee also.
- It will look like it has just added the additional row for the fifth employee. But that’s not true, it effectively destroyed all the <tr> and <td> elements of all the employees and recreated them.
- To confirm this launch your browser with developer tools by pressing F12.
- Then Click on the “Elements” tab and expand the <table> and then <tbody> elements.
- At this point again click the “Refresh Employees” button and you will notice all the <tr>elements are briefly highlighted. This indicates that they are destroyed and recreated.
Initial Page load screen with 4 employees objects:
When we click on “Refresh Employees” button:
In the above screen, you can check that when the button is clicked it will add the fifth object of an employee but along with that it will destroy previously added objects and recreate them. You can see in your browser that they all are highlighted.
This happened because by default angular keeps track of these Employee objects using their object references and when we click the button we are returning new object references(by calling getEmployees() method). So angular does not know whether it is old objects collection or not and that’s why it destroys old list and then recreates them.
This can cause a problem when we are dealing with a large number of objects or list and performance issues will arise. So to avoid this we can use trackBy with ngFor directive.
So now we will add a trackBy function in employeeList.component.ts.
The trackBy function takes the index and the current item as arguments and returns the unique identifier by which that item should be tracked. In our case, we are tracking by Employee code.
trackByEmpCode(index: number, employee: any): string {
return employee.code;
}
updated employee.component.ts
And also make the following change in employee.component.html
Notice that along with ngFor we also specified trackBy.
<tr *ngFor=’let employee of employees; trackBy:trackByEmpCode’>
Now run the application:
At this point, run the application and check the developer tools. When you click “Refresh Employees”the first time, only the row of the fifth employee is highlighted indicating only that<tr> element is added. When you click furthermore, nothing is highlighted. It means that none of the <tr> elements are destroyed or added as the employees collection has not changed. Even now we get different object references when we click “Refresh Employees” button, but as Angular is now tracking employee objects using the employee code instead of object references, the respective DOM elements are not affected.