Strukturelle direktiver (de med *, som *ngIf/) endrer DOM ved å . er syntaktisk sukker — under panseret pakker Angular elementet inn i en og direktivet kontrollerer om/hvordan den malen blir gjengitt.
Strukturelle direktiver (de med *, som *ngIf/) endrer DOM ved å . er syntaktisk sukker — under panseret pakker Angular elementet inn i en og direktivet kontrollerer om/hvordan den malen blir gjengitt.
*ngFor*<ng-template><!-- what you write -->
<p *ngIf="isVisible">Hello</p>
<!-- what Angular actually does -->
<ng-template [ngIf]="isVisible">
<p>Hello</p>
</ng-template>
* forteller Angular: "pakk inn dette elementet i en mal, og la direktivet bestemme når det skal stampes inn i DOM." En <ng-template> er en inert bit med oppmerking som ikke gjengis før et direktiv instansierer det.
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>
De to injiserte bitene er nøkkelen: TemplateRef er elementets mal (det "hva som skal gjengis"), og ViewContainerRef er stedet i DOM (det "hvor"). Direktivet kaller createEmbeddedView for å legge til elementet eller clear for å fjerne det.
<!-- 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> }
Denne nyere syntaksen er mer lesbar og effektiv, selv om det underliggende konseptet med tillegg/fjerning er det samme.
Å forstå * → <ng-template> desugaring avmystifiserer hvordan *ngIf/*ngFor legger til og fjerner DOM, og lar deg bygge egendefinerte strukturelle direktiver (ved hjelp av TemplateRef + ViewContainerRef) for avansert malkontroll — f.eks. tillatelsebasert gjengivelse, egendefinerte gjentakere eller lat stempling.
Det klargjør også hvorfor du ikke kan sette to strukturelle direktiver (*ngIf og *ngFor) på ett element: hver trenger sin egen malwrapper.