How important *ngFor Directive in Angular

*ngFor is a structural directive used to iterate over an array and dynamically generate HTML elements. It works similarly to a for loop, rendering a list of elements in the DOM.

ngFor directive in Angular, a powerful tool for iterating over collections and rendering dynamic content in your templates. Here we understand what it is, how it works, and its common usages, with examples to make it crystal clear.

What is the ngFor Directive?

ngFor is a structural directive in Angular that allows you to loop over an iterable (like an array, list, or any object that supports iteration) and generate HTML elements for each item. It’s similar to a for loop in traditional programming, but it’s declarative and baked into Angular’s template syntax. You’ll typically use it when you need to display a list of items dynamically, such as a list of users, products, or tasks.

The syntax looks like this:

<element *ngFor="let item of items">
  <!-- content using 'item' -->
</element>

*ngFor is the shorthand syntax (with the asterisk), which Angular expands behind the scenes.

  • let item declares a local template variable for each item in the iterable.
  • of items specifies the collection (items) you’re iterating over.

Basic Usage

Suppose you have an array of data in your component, and you want to display it as a list. Here’s how you’d use ngFor:

Component (TypeScript)

import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  fruits = ['Apple', 'Banana', 'Orange', 'Mango'];
}

Template (HTML)

<ul>
  <li *ngFor="let fruit of fruits">{{ fruit }}</li>
</ul>

Output

- Apple
- Banana
- Orange
- Mango

Here, fruit is the local variable representing each element in the fruits array. Angular repeats the <li> element for every item, rendering a neat unordered list.

Key Features and Additional Variables

ngFor provides more than just the item itself—it offers built-in variables to help you manage the loop. These are optional and can be accessed by declaring them in the directive:

  • index: The current item’s index (starting at 0).
  • first: True if the item is the first in the collection.
  • last: True if the item is the last in the collection.
  • even: True if the item’s index is even.
  • odd: True if the item’s index is odd.

Example with Additional Variables

<ul>
  <li *ngFor="let fruit of fruits; let i = index; let isFirst = first; let isLast = last">
    {{ i + 1 }}. {{ fruit }} 
    <span *ngIf="isFirst">(First)</span>
    <span *ngIf="isLast">(Last)</span>
  </li>
</ul>

Output:

1. Apple (First)
2. Banana
3. Orange
4. Mango (Last)

Here, i tracks the index (adjusted to start at 1 for display), and isFirst/isLast add labels to the first and last items.

Using ngFor with Objects:

While ngFor is most commonly used with arrays, you can iterate over an object’s properties if you convert it to an iterable. Angular’s keyvalue pipe is handy for this.

export class ExampleComponent {
  person = {
    name: 'Alice',
    age: 30,
    city: 'New York'
  };
}

Template

<ul>
  <li *ngFor="let entry of person | keyvalue">
    {{ entry.key }}: {{ entry.value }}
  </li>
</ul>

Output

- name: Alice
- age: 30
- city: New York

The keyvalue pipe transforms the object into an array of key-value pairs, which ngFor can then iterate over.

TrackBy for Performance Optimization

When the data in your list changes (e.g., items are added, removed, or updated), Angular re-renders the DOM elements. This can be inefficient for large lists. The trackBy option lets you specify a unique identifier for each item, so Angular only updates the DOM for items that actually change.

export class ExampleComponent {
  items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' }
  ];

  trackByFn(index: number, item: any) {
    return item.id; // Unique identifier
  }
}

Template:

<div *ngFor="let item of items; trackBy: trackByFn">
  {{ item.name }}
</div>

Without trackBy, Angular might re-render all elements even if only one changes. With trackBy, it reuses DOM elements for unchanged items, boosting performance.

Common Usages

Dynamic Lists: Display a list of items from an API, like users or products.html

<div *ngFor="let product of products"> 

{{ product.name }} - ${{ product.price }} 

</div>

Tables: Populate table rows dynamically.html

<table><tr *ngFor="let user of users"> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.email }}</td> </tr> </table>

Nested Loops: Iterate over nested data, like a list of categories with sub-items.html<div *ngFor="let category of categories"> <h3>{{ category.name }}</h3> <ul> <li *ngFor="let item of category.items">{{ item }}</li> </ul> </div>

Conditional Styling: Use loop variables for styling or logic.html<div *ngFor="let item of items; let isEven = even" [ngClass]="{ 'even-row': isEven }"> {{ item }} </div>

Notes:

  • Change Detection: If your array reference doesn’t change (e.g., you’re mutating it with push instead of reassigning), Angular might not detect the update. Use a new array reference (e.g., this.items = […this.items, newItem]) to trigger re-rendering.
  • Syntax: Always use of (not in, which is JavaScript’s syntax). *ngFor=”let item in items” will throw an error.
  • Async Data: Pair ngFor with the async pipe for observables.html<div *ngFor="let item of items$ | async">{{ item }}</div>

Conclusion:

The ngFor directive is a cornerstone of Angular’s templating system, making it easy to render dynamic, data-driven UI components. Whether you’re building simple lists or complex nested structures, it’s flexible and packed with features like trackBy and loop variables to handle real-world scenarios efficiently. If you’ve got a specific use case in mind, let me know, and I’ll tailor an example for you!

Summary:

  • *ngFor dynamically renders elements from an array.
  • Use index to track the position of elements.
  • Use trackBy to optimize rendering performance.
  • Supports nested loops for complex data structures.

Related Posts

Leave a Reply

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