iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
1
Modern Web

Angular 全集中筆記系列 第 10

第 10 型 - 結構型指令 (Structural Directive) - *ngIf

  • 分享至 

  • xImage
  •  

在上一篇利用 *ngFor 指令實作待辦事項清單之後,接著就進一步在增加待辦事項需求。在這一篇將利用 *ngIf 指令,實作下列需求:

  • 當沒有待辦事項資料時,顯示「無任何待辦事項」;反之,顯示清單。

前置作業

在實作需求前,先在 AppComponent 中新增載入與清空資料的功能,以便切換有無待辦事項資料的狀態。

<div>
  <button type="button" (click)="onLoad()">載入資料</button>
  <button type="button" (click)="onClear()">清空資料</button>
</div>
<app-task-list [tasks]="tasks"></app-task-list>
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
  tasks: Task[] = [];

  onLoad(): void {
    this.tasks = [
      new Task("頁面需要顯示待辦事項主旨"),
      new Task("可以設定待辦事項的狀態", TaskState.Doing),
      new Task("當待辦事項狀態為已完的事項無法編輯事項", TaskState.Finish),
    ];
  }

  onClear(): void {
    this.tasks = [];
  }
}

最後,在 task-list.component.css 設定無待辦事項的樣式內容。

div.data-empty {
  margin: 5px;
  font-size: 14pt;
  line-height: 2em;
  text-align: center;
  color: #444;
  border: solid 1px #ccc;
}

利用 *ngIf 指令顯示無任何待辦事項訊息

透過 *ngIf 指令可以將樣版元素在頁面根據特定條件顯示;若條件為 false 時,Angular 會從 DOM 中刪除該樣版元素,並銷毀它來釋放資源。

此一需求可以依傳入的待辦事項清單筆數,來決定所需顯示的資訊。因此,在 task-list.component.html 檔案中,加入無待辦事項時的訊息,並判斷清單筆數是否為零。

<div class="data-empty" *ngIf="tasks.length === 0">無待辦事項</div>

Angular 只允許一個宿主元素放置一個結構型指令 (Structural Directive),因為 <app-task></app-task> 已使用了 *ngFor,所以需要放在外層加上新的元素,以指定判斷待辦事項筆數不為零的條件。

<div class="data-empty" *ngIf="tasks.length === 0">無待辦事項</div>
<div *ngIf="tasks.length !== 0">
  <app-task
    *ngFor="let task of tasks; let odd = odd"
    [class.odd]="odd"
    [subject]="task.subject"
    [(state)]="task.state"
  ></app-task>
</div>

空資料

利用 <ng-container> 避免改變頁面結構

上述實作程式中,在 <app-task> 外層加上 <div> 標籤,用以設定 *ngIf 指令語法。利用 Chrome DevTools 檢視結果,可以看到在待辦事項清單外存在著 <div> 標籤。通常情況下,這層 <div> 標籤的存在並非是問題,但實務上若是需進行套版的狀況,就有可能會影響到整個版型的使用,而導致整個頁面壞掉。

清單資料

針對此議題,Angualr 提供了 <ng-container> 元素,頁面在渲染時不會將此元素放進 DOM 中,故不會汙染樣式或元素結構。接下來,就在 task-list.component.html 檔案中使用此元素。

<div class="data-empty" *ngIf="tasks.length === 0">無待辦事項</div>
<ng-container *ngIf="tasks.length > 0">
  <app-task
    *ngFor="let task of tasks; let odd = odd"
    [class.odd]="odd"
    [subject]="task.subject"
    [(state)]="task.state"
  ></app-task>
</ng-container>

從 Chrome DevTools 中可以發現原本多出來的 <div> 標籤,在利用 <ng-container> 元素之後就不存在了。

NgContainer

利用 ngIfElse 指令顯示無任何待辦事項訊息

除了 *ngIf 之外,也可以利用 Angular 提供的 ngIfElse 語法實作。將需要顯示的頁面內容放在 <ng-template> 元素內,並在 <ng-template> 設定範本參考變數 (Template Reference Variables),讓語法利用此變數設定需要顯示的區塊。

範本參考變數 (Template Reference Variables) 是對所設定的元素、元件或指令的參考,可以在整個頁面範本的任何地方中使用,其語法是利用井號 (#) 進行宣告。

因此,在 task-list.component.html 檔案中,將待辦事項清單移至 <ng-template> 元素內,且設定範本參考變數為 #list,並將空資料顯示區塊移至 <ng-container> 內,利用 *ngIf 指令判斷資料筆數為零時,顯示此元素內區塊,否則顯示 #list 區塊。

<ng-container *ngIf="tasks.length === 0; else list">
  <div class="data-empty">無待辦事項</div>
</ng-container>

<ng-template #list>
  <app-task
    *ngFor="let task of tasks; let odd = odd"
    [class.odd]="odd"
    [subject]="task.subject"
    [(state)]="task.state"
  ></app-task>
</ng-template>

除此之外,也可以進一步把空資料顯示的區塊移至 <ng-template> 元素內,設定範本參考變數為 #dataEmpty;然後在依待辦事項的筆數判斷顯示的對象是 #dataEmpty#list

<ng-container
  *ngIf="tasks.length === 0; then dataEmpty; else list"
></ng-container>

<ng-template #dataEmpty>
  <div class="data-empty">無待辦事項</div>
</ng-template>

<ng-template #list>
  <app-task
    *ngFor="let task of tasks; let odd = odd"
    [class.odd]="odd"
    [subject]="task.subject"
    [(state)]="task.state"
  ></app-task>
</ng-template>

結論

這一篇利用了 *ngIf 結構型指令 (Structural Directive) 實作有無待辦事項資料的顯示切換,實務程式碼放在 GitHub 中。然而,實務上可能會遇到有多個顯示切換的條件,接下著就針對 Angular 內建的另一個指令 - ngSwitch


上一篇
第 9 型 - 結構型指令 (Structural Directive) - *ngFor
下一篇
第 11 型 - 結構型指令 (Structural Directive) - ngSwitch
系列文
Angular 全集中筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言