Question
How can I fix the Angular template error below when trying to render a list of conference talks?
import { bootstrap, Component } from 'angular2/angular2';
@Component({
selector: 'conf-talks',
template: `<div *ngFor="talk of talks">
{{ talk.title }} by {{ talk.speaker }}
<p>{{ talk.description }}</p>
</div>`
})
class ConfTalks {
talks = [
{ title: 't1', speaker: 'Brian', description: 'talk 1' },
{ title: 't2', speaker: 'Julie', description: 'talk 2' }
];
}
@Component({
selector: 'my-app',
directives: [ConfTalks],
template: '<conf-talks></conf-talks>'
})
class App {}
bootstrap(App, []);
Angular reports:
EXCEPTION: Template parse errors:
Can't bind to 'ngFor' since it isn't a known native property
What is incorrect about the *ngFor usage, and what must be imported or configured for Angular to recognize it?
Short Answer
*ngFor is Angular’s structural directive for repeating an element once per item in a collection. You must use its microsyntax correctly—normally let item of items—and make the NgFor directive available to the component. In modern Angular, standalone components import NgFor or CommonModule; NgModule-based components import CommonModule in their module.
Concept
*ngFor is not a native HTML property. It is an Angular structural directive: a feature that changes which parts of the DOM Angular creates.
The asterisk (*) is shorthand syntax. This:
<li *ngFor="let talk of talks">{{ talk.title }}</li>
is conceptually expanded by Angular into an ng-template:
<ng-template ngFor let-talk [ngForOf]="talks">
<li>{{ talk.title }}</li>
</ng-template>
The directive needs two important pieces of information:
talks: the iterable collection to loop through.talk: a local variable representing the current item.
That is why modern Angular syntax uses let talk of talks. Without let, Angular cannot interpret as the loop variable correctly.
Mental Model
Think of *ngFor as a photocopier with a stack of records.
- The collection (
talks) is the stack. - The loop variable (
talk) is the record currently on the copier. - The HTML element is the page to copy.
For every record in talks, Angular creates one copy of the element and fills in expressions such as {{ talk.title }}.
However, the copier must be installed in the room first. Importing NgFor or CommonModule makes the *ngFor feature available to the component.
Syntax and Examples
Use let to declare the local loop variable.
<div *ngFor="let talk of talks">
<h2>{{ talk.title }}</h2>
<p>Presented by {{ talk.speaker }}</p>
<p>{{ talk.description }}</p>
</div>
In a modern standalone Angular component, import NgFor:
import { Component } from '@angular/core';
import { NgFor } from '@angular/common';
@Component({
selector: 'app-conf-talks',
standalone: true,
imports: [NgFor],
template: `
<div *ngFor="let talk of talks">
<h2>{{ talk.title }}</h2>
<p>{{ talk.speaker }}</p>
</div>
`
})
export class {
talks = [
{ : , : , : },
{ : , : , : }
];
}
Step by Step Execution
Consider this component:
@Component({
standalone: true,
imports: [NgFor],
template: `
<p *ngFor="let color of colors">{{ color }}</p>
`
})
export class ColorListComponent {
colors = ['red', 'green', 'blue'];
}
Angular processes it as follows:
- It creates
ColorListComponent. - It evaluates
colors, producing['red', 'green', 'blue']. NgForreceives that array through theof colorsportion.- On the first iteration, Angular sets
colorto'red'and creates<p>red</p>. - On the second iteration, it sets
colorto'green'and creates<p>green</p>. - On the third iteration, it sets
colorto and creates .
Real World Use Cases
*ngFor is used whenever an interface needs to display a collection of data.
- API results: render products returned by an online store API.
- Dashboard tables: show users, invoices, orders, or audit events.
- Navigation: generate menu links from a configuration array.
- Forms: render selectable categories, countries, or tags.
- Chat and activity feeds: show messages and notifications in order.
- Validation messages: display every validation error associated with a form field.
Example: rendering API-loaded products.
<article *ngFor="let product of products">
<h3>{{ product.name }}</h3>
<p>{{ product.price | currency }}</p>
</article>
Real Codebase Usage
In production applications, developers usually combine *ngFor with stable identity, filtering in component code, and empty-state handling.
Track items by a stable identifier
When a list receives updated objects from an API, tracking by ID helps Angular preserve existing DOM elements.
trackByTalkId(index: number, talk: { id: number }): number {
return talk.id;
}
<article *ngFor="let talk of talks; trackBy: trackByTalkId">
{{ talk.title }}
</article>
Handle empty collections
<ul *ngIf="talks.length > 0; else noTalks">
<li *ngFor="let talk of talks">{{ talk.title }}</li>
</ul>
<ng-template #noTalks>
<>No talks are available yet.
Common Mistakes
Forgetting let
Broken modern syntax:
<div *ngFor="talk of talks">
Correct syntax:
<div *ngFor="let talk of talks">
let talk declares a local variable for each item.
Not importing NgFor or CommonModule
A standalone component must explicitly make the directive available:
imports: [NgFor]
or:
imports: [CommonModule]
For an NgModule-based application, import CommonModule into the feature module that declares the component. BrowserModule provides common directives for the root application module, but feature modules should use CommonModule.
Comparisons
| Feature | Purpose | Example | Notes |
|---|---|---|---|
*ngFor | Repeats an element for every item | *ngFor="let item of items" | Use for arrays and other iterables. |
*ngIf | Includes or removes an element based on a condition | *ngIf="isLoggedIn" | Use for conditional display. |
@for | Modern built-in Angular control flow for repetition | @for (item of items; track item.id) { ... } | Available in newer Angular versions; it is an alternative to *ngFor. |
JavaScript for...of | Loops in TypeScript or JavaScript code |
Cheat Sheet
<!-- Current *ngFor syntax -->
<li *ngFor="let item of items">{{ item }}</li>
<!-- Index and first-item state -->
<li *ngFor="let item of items; let i = index; let first = first">
{{ i }}: {{ item }}
</li>
<!-- Track by ID -->
<li *ngFor="let item of items; trackBy: trackById">
{{ item.name }}
</li>
// Standalone component
import { NgFor } from '@angular/common';
@Component({
standalone: true,
imports: [NgFor]
})
// Or import a group of common template tools
import { CommonModule } from '@angular/common';
@Component({
standalone: true,
imports: []
})
FAQ
Why does Angular say ngFor is not a known property?
Angular does not have the NgFor directive in that component’s template scope, or the *ngFor microsyntax is malformed. Import NgFor or CommonModule and use let item of items.
Do I need to import NgFor in every standalone component?
Yes, unless you import CommonModule, another shared import that exports it, or use modern @for control flow instead. Standalone components explicitly declare their template dependencies.
Should I import NgFor or CommonModule?
Import NgFor when that is the only common directive you need. Import CommonModule when the component also needs features such as NgIf, NgSwitch, or common pipes.
What does let talk of talks mean?
It means: for every value in talks, create a local template variable named that refers to the current value.
Mini Project
Description
Build a small conference-talk list that renders data with *ngFor, shows the item number, and displays a useful message when there are no talks. This mirrors a common API-driven UI: a component receives a collection and turns each record into visible content.
Goal
Create a standalone Angular component that safely displays a list of conference talks using NgFor and NgIf.
Requirements
Requirement 1
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.