動態渲染 Component,始之呼吸
Angular 需要什麼樣的要素才能透過其底層 API 建立動態 Component 呢?
總共有三個要素,要渲染什麼(What),渲染在哪(Where),從哪取得 Component(Where 2.0):
知道了始之呼吸三要素之後,我們來建一個 Alert Component 吧!
這個 Component 在資料有異動時會自動出現,並在一段時間後消失
跟前一篇不同的地方是這次不再有 ng-bootstrap 的幫忙,所以能幫助我們更深入了解 => 如何動態建立並顯示 Component
首先自然是要建立 AlertComponent
ng g c alert
接著定義它的 Template
<div class="container mt-2">
<div class="alert alert-warning" role="alert">
The data was refreshed at {{ date | date: "medium" }}
</div>
</div>
接著定義它的 Controller
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.css']
})
export class AlertComponent {
constructor() { }
@Input() date: Date;
}
如同 NodeDetailsComponent,我們要在 app.module.ts 告訴它要幫我們備好一個 Factory class,因此要將 AlertComponent 加到 entryComponents 陣列:
entryComponents: [
NodesDetailComponent,
AlertComponent
],
DashboardComponent 的 template 依然需要一個 placeholder
<ng-template #alertBox></ng-template>
再來就是要填入 AppComponent 的 Controller 了
import { Component, ViewChild, ViewContainerRef, ComponentRef, ComponentFactoryResolver } from '@angular/core';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AlertComponent } from './alert/alert.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
alertRef: ComponentRef<AlertComponent>;
@ViewChild(DashboardComponent) dashboard: DashboardComponent;
@ViewChild('alertBox', { read: ViewContainerRef }) alertBox: ViewContainerRef;
constructor(private ComponentFactoryResolver: ComponentFactoryResolver) { }
alert(date) {
if (!this.alertRef) {
const alertComponent = this.ComponentFactoryResolver.resolveComponentFactory(AlertComponent);
this.alertRef = this.alertBox.createComponent(alertComponent);
}
this.alertRef.instance.date = date;
this.alertRef.changeDetectorRef.detectChanges();
setTimeout(() => this.destroyAlert(), 5000);
}
destroyAlert() {
if (this.alertRef) {
this.alertRef.destroy();
delete this.alertRef;
}
}
refresh() {
this.dashboard.generateData();
}
}
那麼就來調整一下 DashboardComponent 的 controller 如下:
// ...(略)
@Output() onRefresh: EventEmitter<Date> = new EventEmitter<Date>();
//...(略)
generateData() {
//...(略)
this.onRefresh.emit(new Date());
}
最後自然是在發出事件的時候顯示 AlertComponent 了
<app-dashboard (onRefresh)="alert($event)"></app-dashboard>
小結