Angular Structural Directives
Structural directives and Angular's newer control-flow blocks change the DOM's structure by adding, removing, or repeating elements.
Two Ways to Control Structure
Angular offers two syntaxes for conditionally rendering or repeating content: the classic asterisk-prefixed directives (*ngIf, *ngFor) and the newer built-in control flow blocks (@if, @for) introduced in Angular 17. Both achieve the same goal; the block syntax is now the recommended default for new code.
Conditional Rendering
*ngIf removes an element from the DOM entirely when its expression is falsy, rather than just hiding it with CSS - this matters for performance and for any logic tied to the element's presence, such as form validation.
*ngIf (classic syntax)
import { Component } from '@angular/core';
import { NgIf } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-status',
standalone: true,
imports: [NgIf],
template: `
<p *ngIf="isOnline; else offlineBlock">User is online</p>
<ng-template #offlineBlock>
<p>User is offline</p>
</ng-template>
`
})
export class StatusComponent {
isOnline = true;
}
bootstrapApplication(StatusComponent).catch(err => console.error(err));@if (modern control flow)
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-status',
standalone: true,
template: `
@if (isOnline) {
<p>User is online</p>
} @else {
<p>User is offline</p>
}
`
})
export class StatusComponent {
isOnline = true;
}
bootstrapApplication(StatusComponent).catch(err => console.error(err));Repeating Elements
*ngFor and @for both render one copy of a template for each item in a collection. The modern @for block requires an explicit track expression, which helps Angular efficiently update the DOM when the list changes instead of re-rendering everything.
@for with track
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
interface Task {
id: number;
title: string;
}
@Component({
selector: 'app-task-list',
standalone: true,
template: `
<ul>
@for (task of tasks; track task.id) {
<li>{{ task.title }}</li>
} @empty {
<li>No tasks yet</li>
}
</ul>
`
})
export class TaskListComponent {
tasks: Task[] = [
{ id: 1, title: 'Write templates lesson' },
{ id: 2, title: 'Review pipes lesson' }
];
}
bootstrapApplication(TaskListComponent).catch(err => console.error(err));- *ngIf / @if - render an element only when a condition is true
- *ngFor / @for - repeat an element once per item in a list
- @else / *ngIf...else - render an alternative when the condition is false
- @empty - renders when a @for collection has zero items
- track - required in @for; helps Angular identify items across re-renders