接續昨天的範例。
今天要聊的是 ng-container
與 ng-template
<ng-container *ngIf="(products$ | async)?.length > 0; else empty">
<ng-container *ngFor="let item of (products$ | async)"> ...略 </ng-container>
</ng-container>
<ng-template #empty> No Data </ng-template>
上面程式碼所要表達的是,若是資料大於 0 筆,頁面上就會呈現列表,沒有資料的時後在畫面上顯示 No Data
ng-container
ng-container 在 Angular 的 template 裡,它不屬於任何一個 tag
,也不會被渲染出來。
而它通常都會被拿來處理一些邏輯的事情,如 *ngIf
或 *ngFor
。
雖然 *ngIf
、*ngFor
這些也能寫在 div
上,不過 div 它會被呈現出來,有時後會影響排版,這時後 ng-container
就是我們的好朋友惹!
ng-template
因為在 ng-container
有使用到 if/else
,所以這時後就需要一個 ng-template
來做搭配,通常它不會直接顯示出來,而是需要透過其他的指令,如ngIf
或是 TemplateRef
的搭配,當條件成立後,ng-template
裡的內容才會被呈現
TemplateRef
.ts
export class TemplateComponent implements OnInit, AfterViewInit {
@ViewChild('tpl') tplRef!: TemplateRef<any>;
constructor(private viewContainerRef: ViewContainerRef) {}
ngOnInit(): void {}
ngAfterViewInit() {
this.viewContainerRef.createEmbeddedView(this.tplRef);
}
}
.html
<ng-template #tpl> Hello, Angular ! </ng-template>
ng-template 處理多重結構指令
來看一下昨天的 ngIf as
的 範例
<ng-container *ngIf="(products$ | async) as products;">
<ng-container *ngIf="products.length > 0; else empty">
<ng-container *ngFor="let item of products"> ...略 </ng-container>
</ng-container>
</ng-container>
<ng-template #empty> No Data </ng-template>
光是 ng-container
就寫了三層,那有沒有辦法再更簡化一些呢!?
那我們可以使用 ng-template
這樣處理
<ng-container *ngIf="(products$ | async) as products; else empty">
<ng-template *ngIf="products.length > 0" ngFor let-item [ngForOf]="products">
<div class="products">...略</div>
</ng-template>
</ng-container>
後記
在 Angular 裡有一些 xxxOutlet 的指令
如 ngTemplateOutlet
、ngComponentOutlet
接著 明天再來說說 ng-template 與 ngTemplateOutlet 這部份吧
參考資料
NgForOf ViewContainerRef Angular *ngIf variable with async pipe multiple conditions