Angular *ngFor Directive

Introduction

The *ngFor directive is a structural directive that repeats an HTML element for each item in a collection such as an array or iterable object.

For many years, *ngFor has been one of Angular’s most widely used directives. However, starting with Angular 17, Angular introduced the new built-in control flow syntax using @for, and Angular 20+ recommends using @for for new applications because it offers better readability and improved performance.

What is the *ngFor Directive?

*ngFor is a structural directive that repeats an HTML element for each item in a collection.

Note: Angular creates a new DOM element for every item in the array.

For example:

Component:


courses = ['Angular', 'React', 'Vue'];

Template:


<ul>
  <li *ngFor="let course of courses">
    {{ course }}
  </li>
</ul>

Output:

Angular
React
Vue

Instead of writing three <li> elements manually, Angular generates them automatically.

Syntax of *ngFor

Basic syntax:


<div *ngFor="let item of items">
  {{ item }}
</div>

Explanation:

  • let item creates a local variable.
  • of iterates through the collection.
  • items is the array or iterable object.

How *ngFor Works

📖
*ngFor Works:
  • It reads the collection.
  • It creates a template instance for each item.
  • It inserts each generated element into the DOM.
  • When the collection changes, Angular updates the DOM accordingly.

This process is handled automatically through Angular’s change detection mechanism.

Basic Example

Component:


import { Component } from '@angular/core';
@Component({
  selector: 'app-home',
  standalone: true,
  templateUrl: './home.component.html'
})
export class HomeComponent {
  fruits = ['Apple', 'Banana', 'Orange'];
}

Template:


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

Output:

Apple
Banana
Orange

Displaying Objects

Most real-world applications display arrays of objects.

Component:


products = [
  { id: 1, name: 'Laptop', price: 55000 },
  { id: 2, name: 'Mouse', price: 800 },
  { id: 3, name: 'Keyboard', price: 1500 }

];

Template:


<div *ngFor="let product of products">
  <h3>{{ product.name }}</h3>
  <p>₹{{ product.price }}</p>
</div>

Output:

Laptop
₹55000
Mouse
₹800
Keyboard
₹1500

Using the Index

Angular provides the current index.

Example:


<div *ngFor="let course of courses; index as i">
  {{ i + 1 }}. {{ course }}
</div>

Output:

1. Angular
2. React
3. Vue

The index starts from zero.

Using First

Determine whether the current item is the first.


<div *ngFor="let item of items; first as isFirst">
  {{ item }}
  {{ isFirst }}
</div>

Output:

Angular true
React false
Vue false

Using Last

Example:


<div *ngFor="let item of items; last as isLast">
  {{ item }}
</div>

The last variable becomes true only for the final item.

Using Even and Odd

Example:


<div *ngFor="let item of items; even as isEven">
  {{ item }}
</div>

Similarly:


odd as isOdd

These variables are commonly used for alternating row colors.

Using Count

Angular also provides the total number of items.


<div *ngFor="let item of items; count as total">
  {{ total }}
</div>

Useful when displaying list statistics.

Using trackBy

Without trackBy, Angular identifies list items by object reference.

When the list changes, Angular may recreate unnecessary DOM elements.

Example:

Component:


trackById(index: number, product: any) {
  return product.id;
}

Template:


<div *ngFor="let product of products; trackBy: trackById">
  {{ product.name }}
</div>

Benefits:

  • Faster rendering
  • Better performance
  • Less DOM manipulation
  • Ideal for large lists

Nested *ngFor

Example:

Component:


departments = [
  {
    name: 'IT',
    employees: ['John', 'David']
  },
  {
    name: 'HR',
    employees: ['Emma', 'Sophia']
  }
];

Template:


<div *ngFor="let department of departments">
  <h3>{{ department.name }}</h3>
 <ul>
    <li *ngFor="let employee of department.employees">
      {{ employee }}
    </li>
  </ul>
</div>

Angular creates nested lists automatically.

Using *ngFor with API Data

Example:


users = [];
//After fetching data:
this.users = response;

Template:


<div *ngFor="let user of users">
  {{ user.name }}
</div>

Angular automatically updates the displayed list.

Combining *ngFor with *ngIf

Incorrect:


<div *ngFor="let product of products" *ngIf="product.available">

Angular does not allow two structural directives on the same element.

Correct:


<ng-container *ngFor="let product of products">
  <div *ngIf="product.available">
    {{ product.name }}
  </div>
</ng-container>

Alternatively, in Angular 20+, prefer the new control flow syntax using @for and @if.

*ngFor vs @for (Angular 20+)

Angular 17 introduced @for.

*ngFor


<li *ngFor="let course of courses">
  {{ course }
</li>

@for


@for(course of courses; track course) {
<li>{{ course }}</li>
}

Comparison

Feature *ngFor @for
Introduced Early Angular versions Angular 17
Syntax * Structural directive Built-in control flow
Requires * Yes No
Built-in Tracking Optional (trackBy) Native track support
Performance Good Better
Recommended for New Projects Legacy support Yes (Angular 20+)

For new Angular applications, @for is the recommended choice.

*ngFor vs JavaScript for Loop

JavaScript:


for(let i = 0; i < items.length; i++) {
}

Angular:


  <div *ngFor="let item of items">
</div>

Angular automatically creates and manages DOM elements.

Developers only describe what should be displayed rather than how to manipulate the DOM.

Best Practices

1. Use trackBy for Large Lists

Always use trackBy when displaying large datasets.

This significantly improves rendering performance.

2. Keep Templates Simple

Avoid complex expressions inside *ngFor.

Instead of:


{{ calculatePrice(product) }}

Compute values inside the component.

3. Avoid Multiple Structural Directives

Don’t place *ngIf and *ngFor on the same element.

Use:

  • <ng-container>
  • or Angular 20’s @if and @for

4. Prefer @for in New Projects

Angular recommends using the newer built-in control flow syntax for new applications.

5. Use Meaningful Variable Names

Good:


  let product of products

Avoid:


  let x of items

Readable templates are easier to maintain.

Common Mistakes

1. Forgetting let

Incorrect:


*ngFor="product of products"

Correct:


*ngFor="let product of products"

2. Missing trackBy

Large applications without trackBy may experience unnecessary DOM updates.

3. Using Two Structural Directives Together

Incorrect:


<div *ngFor="..." *ngIf="...">

Angular reports an error.

4. Writing Complex Logic

Avoid:


{{ calculateDiscount(product) }}

Move calculations into the component.

Advantages and Disadvantages

Advantages

  • Easy to learn
  • Automatically renders collections
  • Supports arrays and iterable objects
  • Integrates with Angular change detection
  • Supports local variables (index, first, last, even, odd)
  • Works with trackBy for better performance
  • Compatible with API data
  • Reduces repetitive HTML

Disadvantages

  • Large lists without trackBy may affect performance
  • Cannot combine multiple structural directives on the same element
  • Complex template logic reduces readability
  • @for is now preferred for new Angular 20+ projects

Conclusion

The Angular *ngFor directive is one of the most fundamental structural directives for rendering collections of data. It enables developers to generate dynamic lists from arrays or iterable objects with minimal code while keeping templates clean and maintainable.

Although Angular 20+ encourages developers to adopt the modern @for control flow syntax for new projects.

Angular *ngFor Directive – Objective Questions (MCQs)

Q1. *ngFor is used for:






Q2. *ngFor works with:






Q3. Syntax of ngFor uses:






Q4. *ngFor is a:






Q5. ngFor removes or adds:






Related Angular *ngFor Directive Tutorials