Understanding the Syntactic Sugar of Structural Directives
The asterisk * syntax is shorthand that tells Angular to wrap the element inside an <ng-template> and attach the structural directive to it.
Understanding this mechanism helps when you need to:
- use multiple structural directives (which is not allowed with the
*syntax on the same element), - or be explicit about how Angular transforms the template.
⚠️ Since Angular 17, a new control flow syntax (
@if,@for,@switch) has been introduced as a modern alternative to*ngIf,*ngFor, and*ngSwitch.
The examples below show the classic syntax still widely used in many projects.
Desugaring *ngIf
Section titled “Desugaring *ngIf”<div *ngIf="condition">Hello</div>is equivalent to:
<ng-template [ngIf]="condition"> <div>Hello</div></ng-template>Angular automatically converts the *ngIf syntax into an <ng-template> with the ngIf directive.
Desugaring *ngFor
Section titled “Desugaring *ngFor”<div *ngFor="let item of items; index as i">{{ i }} {{ item }}</div>becomes:
<ng-template ngFor let-item [ngForOf]="items" let-i="index"> <div>{{ i }} {{ item }}</div></ng-template>Explanation:
let-itemcreates a template variable calleditem[ngForOf]="items"binds the iterable collectionlet-i="index"binds the index value to variablei
Desugaring *ngSwitch
Section titled “Desugaring *ngSwitch”<div [ngSwitch]="value"> <div *ngSwitchCase="'A'">A</div> <div *ngSwitchDefault>Default</div></div>becomes:
<div [ngSwitch]="value"> <ng-template [ngSwitchCase]="'A'"> <div>A</div> </ng-template>
<ng-template ngSwitchDefault> <div>Default</div> </ng-template></div>Combining structural directives
Section titled “Combining structural directives”An element can only have one structural directive using *.
For example, this is not valid:
<div *ngIf="condition" *ngFor="let item of items"></div>To solve this, you can use:
<ng-container>- explicit
<ng-template>wrappers
Example:
<ng-container *ngIf="condition"> <div *ngFor="let item of items">{{ item }}</div></ng-container>New Angular Control Flow Syntax (Angular 17+)
Section titled “New Angular Control Flow Syntax (Angular 17+)”Angular introduced a syntax closer to JavaScript control flow.
Example with @if:
@if (condition) { <div>Hello</div>}Example with @for:
@for (item of items; track item) { <div>{{ item }}</div>}Example with @switch:
@switch (value) { @case ('A') { <div>A</div> } @default { <div>Default</div> }}This modern syntax:
- improves readability
- reduces the need for
<ng-template> - feels closer to standard programming control flow
💡 Even though the
*syntax is convenient, understanding the desugared (ng-template) form is essential for advanced scenarios such as creating custom structural directives or working with multiple template bindings.