التوجيهات البنيوية (تلك التي تحتوي على *، مثل *ngIf/*ngFor) تغير DOM بـ . هي مجرد سكر نحوي — تحت غطاء المحرك، يقوم Angular بتغليف العنصر في والتوجيه يتحكم في ما إذا كان سيتم عرض هذا القالب وكيفية عرضه.
التوجيهات البنيوية (تلك التي تحتوي على *، مثل *ngIf/*ngFor) تغير DOM بـ . هي مجرد سكر نحوي — تحت غطاء المحرك، يقوم Angular بتغليف العنصر في والتوجيه يتحكم في ما إذا كان سيتم عرض هذا القالب وكيفية عرضه.
*<ng-template><!-- what you write -->
<p *ngIf="isVisible">Hello</p>
<!-- what Angular actually does -->
<ng-template [ngIf]="isVisible">
<p>Hello</p>
</ng-template>
* يخبر Angular: "غلف هذا العنصر في قالب، واسمح للتوجيه بأن يقرر متى يضيفه إلى DOM." <ng-template> هي مقطع من العلامات الخامل لا يتم عرضه حتى يقوم التوجيه بإنشاء مثيل له.
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>
القطعتان المحقونتان هما المفتاح: TemplateRef هي قالب العنصر ("ما يتم عرضه")، و ViewContainerRef هي الموقع في DOM ("أين"). يستدعي التوجيه createEmbeddedView لإضافة العنصر أو clear لإزالته.
<!-- 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> }
هذا البناء الجديد أكثر سهولة في القراءة وأكثر كفاءة، على الرغم من أن مفهوم الإضافة/الإزالة الأساسي هو نفسه.
فهم إلغاء السكر النحوي * → <ng-template> يوضح كيفية إضافة وإزالة DOM بواسطة *ngIf/*ngFor، ويسمح لك ببناء توجيهات بنيوية مخصصة (باستخدام TemplateRef + ViewContainerRef) للتحكم المتقدم في القوالب — على سبيل المثال، العرض المستند إلى الأذونات، أو التكرارات المخصصة، أو الإضافة البطيئة.
كما يوضح السبب في عدم إمكانية وضع توجيهين بنيويين (*ngIf و *ngFor) على عنصر واحد: كل منهما يحتاج إلى غلاف قالب خاص به.