zoukankan      html  css  js  c++  java
  • [Angular 2] Generate Angular 2 Components Programmatically with entryComponents & ViewContainerRef

    You can generate Angular 2 components using a combination of ViewContainer and ComponentFactory, but you must always remember to add the components you want to generate to your list of entryComponents otherwise the compiler will optimize the component class out of your project.

    ViewChild:

    For example, in HomComponent, we created a div with ref "#container", if you log out the element we can see:

    import {Component, ViewChild} from '@angular/core';
    import {SimpleService} from "../../serivces/simple.service";
    
    @Component({
        moduleId: module.id,
        selector: 'home',
        template: '<div #container></div>'
    })
    export class HomeComponent {
    
        @ViewChild('container') container;
    
        constructor(private simpleService: SimpleService) {
        }
    
        ngAfterContentInit(){
    
        }
    
    }

    It is a native Element. 

    Actually you can View the child in other different way:

        @ViewChild('container', {
            read: ViewContainerRef
        }) container;

    "ViewContainerRef": Represents a container where one or more Views can be attached.

    For example we now want to create component Programmatically:

    import {Component, ViewChild, ViewContainerRef, ComponentFactoryResolver} from '@angular/core';
    import {WidgetThree} from "../widgets/widget-three.component";
    
    @Component({
        moduleId: module.id,
        selector: 'home',
        template: '<div #container></div>'
    })
    export class HomeComponent {
    
        @ViewChild('container', {
            read: ViewContainerRef
        }) container;
    
        constructor(private resolver: ComponentFactoryResolver) {
        }
    
        ngAfterContentInit(){
    
            const WidgetFactory = this.resolver.resolveComponentFactory(WidgetThree);
            this.container.createComponent(
                WidgetFactory
            )
        }
    
    }

    See https://angular.io/docs/ts/latest/api/core/index/ViewContainerRef-class.html

    But now, it won't work:

    It says it cannot find WidgetThree, even we already define in Module:

    import { NgModule} from '@angular/core';
    import { CommonModule } from '@angular/common';
    import {WidgetOneComponent} from './widget-one.component';
    import {WidgetTwoComponent} from './widget-two.component';
    import {WidgetThree} from './widget-three.component';
    
    @NgModule({
        imports: [CommonModule],
        declarations: [WidgetOneComponent, WidgetTwoComponent, WidgetThree],
        exports: [WidgetOneComponent, WidgetTwoComponent, WidgetThree, CommonModule]
    })
    export class WidgetsModule {
    
    }

    The problem for that is because Angualr2 optimize the imports component, check whether it is used in template, if not, then remove the component from the bundle file. Because in HomeComponent tempalte, we didn't use WidgetThree compoennt, so it was removed.

    To solve the problem, we can use "entryComponents":

    import { NgModule} from '@angular/core';
    import { CommonModule } from '@angular/common';
    import {WidgetOneComponent} from './widget-one.component';
    import {WidgetTwoComponent} from './widget-two.component';
    import {WidgetThree} from './widget-three.component';
    
    @NgModule({
        imports: [CommonModule],
        declarations: [WidgetOneComponent, WidgetTwoComponent, WidgetThree],
        entryComponents: [WidgetThree],
        exports: [WidgetOneComponent, WidgetTwoComponent, WidgetThree, CommonModule]
    })
    export class WidgetsModule {
    
    }

    "entryComponents" just tell angular, no matter what, keep the componet into the bundle, don't remove it.

    And now, we can actually create multi WidgetThree component programmatically:

    export class HomeComponent {
    
        @ViewChild('container', {
            read: ViewContainerRef
        }) container;
    
        constructor(private resolver: ComponentFactoryResolver, private simpleService: SimpleService) {
        }
    
        ngAfterContentInit(){
            const WidgetFactory = this.resolver.resolveComponentFactory(WidgetThree);
            this.container.createComponent(WidgetFactory);
            this.container.createComponent(WidgetFactory);
            this.container.createComponent(WidgetFactory);
            this.container.createComponent(WidgetFactory);
            this.container.createComponent(WidgetFactory);
        }
    
    }
  • 相关阅读:
    关于在函数中返回动态的内存
    C与C++中的const
    strcat函数的坑点
    面试题30.最小的k个数
    面试题29.数组中出现次数超过一半的数字
    面试题28.字符串的排列
    面试题27.二叉搜索树与双向链表
    C++中构造函数初始化成员列表总结
    Oracle merge into
    检索 COM 类工厂中 CLSID 解决办法
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5898553.html
Copyright © 2011-2022 走看看