Structural Directives (*ngIf, *ngFor)
Control what renders and how many times using the classic structural directives and the modern @if/@for control-flow syntax.
What Is a Structural Directive?
A structural directive changes the actual structure of the DOM — adding, removing, or repeating elements — rather than just setting a property. Classic structural directives are prefixed with an asterisk in templates, a shorthand for a more verbose underlying syntax.
*ngIf
*ngIf adds or removes an element from the DOM entirely, based on whether its expression is truthy.
<p *ngIf="isLoggedIn">Welcome back!</p><p *ngIf="!isLoggedIn">Please log in.</p>For an else branch, use ng-template with a template reference.
<p *ngIf="isLoggedIn; else loggedOut">Welcome back!</p><ng-template #loggedOut> <p>Please log in.</p></ng-template>*ngFor
*ngFor repeats an element once per item in an array, following a "let item of items" syntax.
<ul> <li *ngFor="let fruit of fruits; let i = index"> {{ i }}: {{ fruit }} </li></ul>For large or frequently-changing lists, add trackBy (classic *ngFor) or rely on @for's required track expression (modern syntax) so Angular can correctly identify and reuse DOM nodes across updates instead of recreating everything.
The Modern @if / @for Syntax
Modern Angular (17+) introduces a new, built-in control-flow syntax — @if, @for, @switch — that replaces *ngIf/*ngFor with cleaner syntax and better performance, without needing CommonModule imported at all.
@if (isLoggedIn) { <p>Welcome back!</p>} @else { <p>Please log in.</p>}
<ul> @for (fruit of fruits; track fruit) { <li>{{ fruit }}</li> } @empty { <li>No fruits available.</li> }</ul>| Classic | Modern |
|---|---|
| *ngIf="cond" | @if (cond) { ... } |
| *ngIf="cond; else tpl" | @if (cond) { ... } @else { ... } |
| *ngFor="let x of items" | @for (x of items; track x) { ... } |
| Requires CommonModule import | Built into the template compiler, no import needed |
Common Beginner Mistakes
Classic structural directives require CommonModule in a standalone component's imports array — the modern @if/@for syntax avoids this entirely.
Unlike *ngFor's optional trackBy, @for requires a track expression — Angular won't compile without one.
FAQs
Use the modern @if/@for/@switch syntax for new projects — it's simpler, doesn't need CommonModule, and performs better. This course uses classic syntax in early examples for broad familiarity, then shows the modern equivalent.
Very close — both conditionally render content, though @if compiles more efficiently and its @else if chains are more readable than nested *ngIf/ng-template combinations.
Summary
Structural directives control whether and how many times something renders, with modern Angular's @if/@for offering a cleaner, import-free alternative to the classic asterisk syntax. Next, you'll learn attribute directives, which modify an existing element rather than adding/removing it.