Angular Trackby: Improve ngFor Performance
Angular framework provides a lot of directives and features to help developers in building dynamic web applications. One of the core features is the ngFor
directive, used to render a list of items from an array. However, when working with large or complex lists, the performance of ngFor
can be an issue. That’s where Angular’s trackBy
feature comes in.
What is ngFor?
The ngFor
directive is used to render a list of items from an array in Angular. It iterates over the elements of an array and creates a template instance for each element. The ngFor
directive is mainly used with an Angular component, and the template is used to render the list on the web page.
What is the Problem with ngFor?
The ngFor
directive is a powerful Angular feature, but when working with large or complex lists, the performance of ngFor
can be an issue. The problem arises when a change occurs in the list. Angular re-renders all the list elements, even if only a single element has changed. This can result in a significant performance hit, especially in large lists or when dealing with complex components.
How can we improve ngFor performance?
The performance of ngFor
can be improved by using Angular’s trackBy
feature. The trackBy
function tells Angular how to track changes in the list.
By default, Angular tracks changes in the list using the item’s identity, that is, by comparing the object references. If the object references are different, Angular treats the objects as different and re-renders the template. But, when using the trackBy
function, Angular tracks the items based on the value returned by the function and not based on the item’s identity.
When the trackBy
function is used to track changes in the list, Angular only re-renders the list items that have changed, resulting in much better performance, especially when working with large lists or complex components.
How to use trackBy in ngFor?
To use the trackBy
function in ngFor
, follow these steps:
- Create a method in your component that returns a unique identifier for each item in the list.
- Bind the method to the
ngFor
directive using thetrackBy
attribute. - Use the unique identifier returned by the method to track changes in the list.
Step 1: Create a method in your component that returns a unique identifier for each item in the list
Here’s an example of a component that uses the ngFor
directive but does not use a trackBy
function:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
List of books
{{ book.title }}
`
})
export class AppComponent {
books = [
{ id: 1, title: 'The Alchemist' },
{ id: 2, title: 'The Power of Now' },
{ id: 3, title: 'Rich Dad Poor Dad' }
];
}
In this component, the ngFor
directive loops over the books
array and creates a list of books on the web page. The problem with this approach is that if a change occurs in the list, such as adding or removing a book, Angular will re-render all the list items, even if only a single book has changed.
To solve this problem, we need to create a method that returns a unique identifier for each book. For example, we can use the id
property of each book as the unique identifier:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
List of books
{{ book.title }}
`
})
export class AppComponent {
books = [
{ id: 1, title: 'The Alchemist' },
{ id: 2, title: 'The Power of Now' },
{ id: 3, title: 'Rich Dad Poor Dad' }
];
trackByFn(index: number, book: Book): number {
return book.id;
}
}
interface Book {
id: number;
title: string;
}
In this example, we have added a method called trackByFn
that takes the index of the item and the item itself as arguments and returns the unique identifier for the item.
Step 2: Bind the method to the ngFor directive using the trackBy attribute
The second step is to bind the trackByFn
method to the ngFor
directive using the trackBy
attribute:
Here, we have added the trackBy
attribute to the ngFor
directive and set its value to the name of the method that returns the unique identifier for each book.
Step 3: Use the unique identifier returned by the method to track changes in the list
In the third step, we use the unique identifier returned by the trackByFn
method to track changes in the list. Angular compares the unique identifiers of the items instead of their object references when tracking changes.
FAQs
What is the difference between using a trackBy function and not using it?
When using a trackBy function, Angular only re-renders the list items that have changed, resulting in much better performance, especially when working with large lists or complex components.
When not using a trackBy function, Angular re-renders all the list items, even if only a single element has changed. This can result in a significant performance hit, especially in large lists or when dealing with complex components.
What is the benefit of using a trackBy function?
The benefit of using a trackBy function is that it improves the performance of ngFor
by reducing the number of list items that need to be re-rendered when a change occurs in the list.
Can we use any property of the item as the unique identifier?
Yes, we can use any property of the item as the unique identifier as long as it is unique for each item.
Can we use the index of the item as the unique identifier?
It is not recommended to use the index of the item as the unique identifier, as this can cause issues when adding or removing items from the list. Angular doesn’t guarantee that the indexes will remain the same when the list changes.
Can we use a function that generates a unique identifier for each item?
Yes, we can use a function that generates a unique identifier for each item as the trackBy
function. However, the function must return the same value for the same item every time it is called.
What happens if two items have the same unique identifier?
If two items have the same unique identifier, Angular will treat them as the same item and may cause unexpected behavior.