在上一篇利用 *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>
元素之後就不存在了。
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
。