Les directives structurelles (celles avec *, comme *ngIf/) modifient le DOM en . Le est du sucre syntaxique — en arrière-plan, Angular enveloppe l'élément dans un et la directive contrôle si/comment ce template est rendu.
Les directives structurelles (celles avec *, comme *ngIf/) modifient le DOM en . Le est du sucre syntaxique — en arrière-plan, Angular enveloppe l'élément dans un et la directive contrôle si/comment ce template est rendu.
*ngFor*<ng-template><!-- what you write -->
<p *ngIf="isVisible">Hello</p>
<!-- what Angular actually does -->
<ng-template [ngIf]="isVisible">
<p>Hello</p>
</ng-template>
Le * dit à Angular : « enveloppe cet élément dans un template, et laisse la directive décider quand l'ajouter au DOM ». Un <ng-template> est un bloc de markup inerte qui n'est pas rendu jusqu'à ce qu'une directive l'instancie.
import { Directive, Input, TemplateRef, ViewContainerRef } from "@angular/core";
@Directive({ selector: "[appUnless]" }) // *appUnless = "the opposite of ngIf"
export class UnlessDirective {
constructor(
private templateRef: TemplateRef<any>, // the wrapped <ng-template>
private viewContainer: ViewContainerRef, // where to render it
) {}
@Input() set appUnless(condition: boolean) {
if (!condition) {
this.viewContainer.createEmbeddedView(this.templateRef); // render it
} else {
this.viewContainer.clear(); // remove it
}
}
}
// usage: <p *appUnless="isHidden">Shown when isHidden is false</p>
Les deux éléments injectés sont la clé : TemplateRef est le template de l'élément (le « quoi rendre »), et ViewContainerRef est l'emplacement dans le DOM (le « où »). La directive appelle createEmbeddedView pour ajouter l'élément ou clear pour le supprimer.
<!-- newer Angular replaces *ngIf/*ngFor with built-in block syntax -->
@if (isVisible) { <p>Hello</p> } @else { <p>Hidden</p> }
@for (item of items; track item.id) { <li>{{ item.name }}</li> }
Cette nouvelle syntaxe est plus lisible et performante, bien que le concept sous-jacent d'ajout/suppression soit le même.
Comprendre le desugaring * → <ng-template> démystifie comment *ngIf/*ngFor ajoutent et suppriment le DOM, et vous permet de construire des directives structurelles personnalisées (en utilisant TemplateRef + ViewContainerRef) pour un contrôle avancé des templates — par exemple le rendu basé sur les permissions, des répéteurs personnalisés, ou l'ajout différé.
Cela clarifie aussi pourquoi vous ne pouvez pas mettre deux directives structurelles (*ngIf et *ngFor) sur un même élément : chacune a besoin de son propre wrapper template.