Structural directives shape the DOM itself by adding, removing, or repeating elements based on data. This lesson covers the classic * directives and the modern built-in control flow syntax side by side.
What Are Structural Directives?
Structural directives change the structure of the DOM, unlike attribute directives, which only change an existing element's appearance or behavior. The most common examples are conditionally showing content and repeating content for each item in a list.
Classic structural directives are prefixed with an asterisk (*ngIf, *ngFor), which is syntactic sugar Angular expands into an <ng-template> behind the scenes. Since Angular 17, a built-in block syntax (@if, @for, @switch) provides the same capability more efficiently.
By default, Angular tracks list items by reference identity. When a list is replaced with a new array of objects representing the same logical items (for example, after refetching from an API), Angular may destroy and recreate every DOM node unnecessarily. trackBy (classic) and track (modern, required) tell Angular how to recognize the "same" item across renders.
The modern @for block supports an @empty branch that renders automatically when the collection has zero items, removing the need for a separate *ngIf check.
Using @for without a track expression; unlike *ngFor's optional trackBy, track is mandatory in the modern syntax.
Tracking by array index when list items can be reordered, causing incorrect item identity across renders.
Nesting multiple *ngIf/*ngFor on the same element instead of using <ng-container> or the modern block syntax to avoid extra wrapper elements.
Forgetting CommonModule in a standalone component's imports when still using classic *ngIf/*ngFor.
Key Takeaways
Structural directives add, remove, or repeat DOM elements based on data.
*ngIf/*ngFor/*ngSwitch are the classic syntax; @if/@for/@switch are the modern, recommended replacement.
track/trackBy help Angular correctly identify list items across re-renders, improving performance and preserving UI state.
@for includes a built-in @empty branch for empty-collection UI.
Pro Tip
When migrating a codebase, the Angular CLI includes an automated schematic, ng generate @angular/core:control-flow, that rewrites *ngIf/*ngFor/*ngSwitch templates to the modern @if/@for/@switch syntax for you.
You now understand structural directives in depth. Next, learn about Attribute Directives, which change appearance and behavior without altering DOM structure.