Mastering ngFor in Angular

Angular’s *ngFor directive is a powerful structural directive used to dynamically render elements for each item in a collection. It is fundamental for building dynamic lists, tables, menus, and other repetitive UI elements.

This guide covers:

  1. Introduction to *ngFor
  2. Basic syntax and usage
  3. Iterating over arrays
  4. Using index and first/last flags
  5. Nested *ngFor loops
  6. Rendering objects and key-value pairs
  7. Combining *ngFor with other directives
  8. Dynamic lists with events
  9. Performance considerations and best practices
  10. Summary

1. Introduction to *ngFor

*ngFor is an Angular structural directive that adds or removes DOM elements based on an array or collection in the component.

  • Dynamic rendering: Automatically updates the DOM when the collection changes.
  • Reusable patterns: Can render lists, tables, dropdowns, and grids.
  • Template-driven: Works seamlessly with Angular templates and property binding.

2. Basic Syntax and Usage

The basic syntax of *ngFor:

<li *ngFor="let item of items">{{ item }}</li>
  • let item of items iterates over the array items.
  • item represents the current element in the iteration.
  • The element is created for each array item.

Example

// component.ts
products = ['Laptop', 'Phone', 'Tablet'];
<ul>
  <li *ngFor="let product of products">{{ product }}</li>
</ul>
  • Renders three list items for Laptop, Phone, and Tablet.

3. Iterating Over Arrays

*ngFor works with arrays of primitives or objects.

3.1 Array of Strings

categories = ['Electronics', 'Clothing', 'Books'];
<ul>
  <li *ngFor="let category of categories">{{ category }}</li>
</ul>

3.2 Array of Objects

products = [
  { name: 'Laptop', price: 1200 },
  { name: 'Phone', price: 800 },
  { name: 'Tablet', price: 600 }
];
<ul>
  <li *ngFor="let product of products">
{{ product.name }} - ${{ product.price }}
</li> </ul>
  • Access properties of each object using item.property.

4. Using Index and First/Last Flags

Angular provides local variables inside *ngFor:

  • index → current iteration index
  • first → true if first item
  • last → true if last item
  • even / odd → boolean flags for even/odd items

Example

<ul>
  <li *ngFor="let product of products; let i = index; let first = first; let last = last; let even = even">
{{ i + 1 }}. {{ product.name }}
&lt;span *ngIf="first"&gt;- First Item&lt;/span&gt;
&lt;span *ngIf="last"&gt;- Last Item&lt;/span&gt;
&lt;span *ngIf="even"&gt;- Even&lt;/span&gt;
</li> </ul>
  • Provides enhanced context about the loop iteration.
  • Useful for conditional styling or labels.

5. Nested *ngFor Loops

You can use *ngFor inside another *ngFor to render nested collections.

Example: Categories with Products

categories = [
  { name: 'Electronics', items: ['Laptop', 'Phone'] },
  { name: 'Books', items: ['Novel', 'Comics'] }
];
<div *ngFor="let category of categories">
  <h3>{{ category.name }}</h3>
  <ul>
&lt;li *ngFor="let item of category.items"&gt;{{ item }}&lt;/li&gt;
</ul> </div>
  • Outer loop renders categories.
  • Inner loop renders products within each category.

6. Rendering Objects and Key-Value Pairs

Angular can iterate over object entries using keyvalue pipe.

Example: Object Iteration

user = { name: 'John', age: 30, email: '[email protected]' };
<ul>
  <li *ngFor="let item of user | keyvalue">
{{ item.key }}: {{ item.value }}
</li> </ul>
  • Renders all key-value pairs dynamically.

7. Combining *ngFor with Other Directives

*ngFor can be combined with:

  • *ngIf for conditional rendering
  • [ngClass] and [ngStyle] for dynamic styles

Example: Highlight Expensive Products

<ul>
  <li *ngFor="let product of products" [ngClass]="{'expensive': product.price > 1000}">
{{ product.name }} - ${{ product.price }}
</li> </ul>
.expensive { font-weight: bold; color: red; }
  • Highlights items based on a condition dynamically.

8. Dynamic Lists with Events

*ngFor works well with event binding, enabling interactive lists.

Example: Delete Item from List

products = ['Laptop', 'Phone', 'Tablet'];

deleteProduct(product: string) {
  this.products = this.products.filter(p => p !== product);
}
<ul>
  <li *ngFor="let product of products">
{{ product }}
&lt;button (click)="deleteProduct(product)"&gt;Delete&lt;/button&gt;
</li> </ul>
  • Clicking delete removes the item dynamically.
  • Angular updates the DOM automatically.

9. Performance Considerations and Best Practices

9.1 Use TrackBy

Angular re-renders lists on change by default. Use trackBy for large lists:

<li *ngFor="let product of products; trackBy: trackByFn">
  {{ product.name }}
</li>
trackByFn(index: number, product: any) {
  return product.id; // unique identifier
}
  • Improves performance by reusing existing DOM elements.

9.2 Avoid Nested Loops for Large Data

  • Nested *ngFor can cause performance issues for large collections.
  • Consider flattening data or using virtual scrolling.

9.3 Use Pipes for Filtering/Sorting

  • Filter or sort arrays before binding, or use Angular custom pipes.
<li *ngFor="let product of products | filter: searchText">{{ product.name }}</li>

10. Summary

*ngFor is an essential Angular directive for:

  • Iterating over arrays and objects
  • Creating dynamic lists and tables
  • Accessing contextual variables like index, first, last
  • Nesting loops for complex structures
  • Combining with events, pipes, and directives for interactive UIs
  • Optimizing performance with trackBy

It forms the backbone of dynamic template rendering in Angular applications, making it a critical tool for developers building modern web applications.


Combined Example: Dynamic Product List

products = [
  { id: 1, name: 'Laptop', price: 1200 },
  { id: 2, name: 'Phone', price: 800 },
  { id: 3, name: 'Tablet', price: 600 }
];

deleteProduct(product: any) {
  this.products = this.products.filter(p => p.id !== product.id);
}
<ul>
  <li *ngFor="let product of products; trackBy: trackByFn" [ngClass]="{'expensive': product.price > 1000}">
{{ product.name }} - ${{ product.price }}
&lt;button (click)="deleteProduct(product)"&gt;Delete&lt;/button&gt;
</li> </ul>
trackByFn(index: number, product: any) {
  return product.id;
}
  • Demonstrates dynamic rendering, styling, deletion, and performance optimization with *ngFor.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *