因為會忘,所以要寫下來

Angular ng-container 與 ng-template

2 minutes to read

接續昨天的範例。 今天要聊的是 ng-containerng-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 的指令 如 ngTemplateOutletngComponentOutlet 接著 明天再來說說 ng-template 與 ngTemplateOutlet 這部份吧

參考資料

NgForOf ViewContainerRef Angular *ngIf variable with async pipe multiple conditions

對這篇文章有什麼想法嗎?

Copyright © 2023 Mandy. All rights reserved. Build with Astro