iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
1
Modern Web

Angular新手村學習筆記(2019)系列 第 10

Day10_動態產生元件及應用

  • 分享至 

  • xImage
  •  

其他與相關的精彩文章

今天主要是

[S06E09] 動態產生元件及應用

https://www.youtube.com/watch?v=282ITUdC12Y&list=PL9LUW6O9WZqgUMHwDsKQf3prtqVvjGZ6S&index=4

這一集是由 Felix Tsai 老師來分享der,感謝大神

首先,先開好片頭導讀的文章,再跟著影片一起看,以後才有能力自己查文件

  1. 開啟 https://angular.io
  2. FUNDAMENTALS / Components & Templates / Dynamic Components
    https://angular.io/guide/dynamic-component-loader

使用情境:
當Templates不固定時,透過runtime來動態產生Component

重要的API:
ComponentFactoryResolver
用來建component的instance
https://angular.io/api/core/ComponentFactoryResolver

The anchor(錨點) directive

        ^^^ 錨點,包成一個Directive

https://angular.io/guide/dynamic-component-loader#the-anchor-directive

ViewContainerRef

可用放Component的Container
可將多個Views附加到Component的Container
https://angular.io/api/core/ViewContainerRef

  1. dynamic.directive.ts 定義 Directive
import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[dynamic-host]',
})
export class DynamicDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}
  1. app.module.ts 宣告 Directive
@NgModule({
    declarations: [DynamicDirective], // Directive放在declarations
    entryComponents: [ComponentAComponent,ComponentBComponent] // 動態載入的元件加在這裡,避免被ng build移除
})
  1. app.component.html 增加anchor(錨點)
<ng-template dynamic-host></ng-template>
                ^^^ 加入anchor(錨點)
  1. 建立2個要動態產生的component

  2. app.component.ts 動態產生元件

import { Component, ComponentFactoryResolver, ViewChild, AfterViewInit } from '@angular/core';
import { DynamicDirective } from './dynamic.directive';
// 要動態產生的Component
import { ComponentAComponent } from ...;
import { ComponentBComponent } from ...;
@Component({...})
export class AppComponent implements AfterViewInit {
    // 在app.component.html注入的ViewContainerRef
    // anchor(錨點)
    @ViewChild(DynamicDirective) dynamicHost; 
    
    constructor(private resolver: ComponentFactoryResolver){}

    ngAfterViewInit(){
        // 專門生產ComponentAComponent instance的factory
        const factory = this.resolver.resolverComponentFactory(ComponentAComponent);
        
        // 在app.component.html注入的ViewContainerRef
        // <ng-template dynamic-host></ng-template>
        const ref = this.dynamicHost.viewContainerRef;
        
        // https://angular.io/api/core/ViewContainerRef#createcomponent
        // 實例化一個component,並host view插入viewContainerRef
        ref.createComponent(factory);
    }
}

在(錨點)上,動態切換Component

  1. app.component.html 增加anchor(錨點)
<input type="radio" name="showComponent" (change)="onRadioChange('A')" >
<label for="showComponent">select component A</label>
<input type="radio" name="showComponent" (change)="onRadioChange('B')" >
<label for="showComponent">select component B</label>
<ng-template dynamic-host></ng-template>
                ^^^ 加入anchor(錨點)
  1. app.component.ts
onRadioChange(value){
    const factory = this.resolver.resolverComponentFactory(componentMapping[value]); 
                                        ^^^^^^^^^^^^^^^^^^^^^
    const ref = this.dynamicHost.viewContainerRef;
    ref.clear(); // 沒clear()的話,舊的component會一直存在
    ref.createComponent(factory);
}

export const componentMapping = {
    A: ComponentAComponent,
    B: ComponentBComponent,
}

如果有多個anchor(錨點)

@ViewChildren(DynamicDirective) dynamicHost; // 多個anchor(錨點)
^^^^^^^^^^^^^ 複數型
onRadioChange(value){
    const factory = this.resolver.resolverComponentFactory(componentMapping[value]); 
                                         // 對每個anchor(錨點)操作
    const ref = this.dynamicHost._results.forEach(item => {
                                    ^^^
        const ref = item.viewContainerRef; 
        ref.clear(); // 沒clear()的話,舊的component會一直存在
        ref.createComponent(factory);
    });
}

動態產生元件 的 應用

A 報表 -- A報表的Filter (其Input,DateTimePicker,Select)
B 報表 -- B報表的Filter (其Input,DateTimePicker,Select)

此處 Felix 大大分享珍貴的應用,圖難以畫出,請大家看影片19分的地方

FilterBase<T>打出來,以後自己參考用

FilterBase<T>
value: T, // 泛型
key:string,
type:string // 例如:Input、DataTimePicker、Select
sort:number, // 欄位的順序
validation: any // reactive form的validation

動態產生的元件,傳參數

  1. component-a.component.ts
@Input() data = ''; // 假設要動態產生的元件有一個參數 data

// 其他應用
@Input() form: FormGroup; // 丟form進去動態元件
  1. app.component.ts
    @ViewChild(DynamicDirective) dynamicHost;  
    constructor(private resolver: ComponentFactoryResolver){}

    ngAfterViewInit(){
        const factory = this.resolver.resolverComponentFactory(ComponentAComponent);
        const ref = this.dynamicHost.viewContainerRef;
        const instance = ref.createComponent(factory).instance;
                                        create完取得實體 ^^^^
        instance.data = 'abc';
    }

上一篇
Day09_Form Part II - Reactive Form
下一篇
Day11_土炮 Tab 元件 - 使用 ControlValueAccessor
系列文
Angular新手村學習筆記(2019)33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言