2017-03-06 43 views
3

我的控制器有一個我想在頁面內部擁有的組件列表。這些其他組件是獨立創建和正確工作的。Angular 2在ng中動態創建組件

在我的HTML模板:

<ng-container *ngFor="let component of components"> 
    <div {{component.name}}></div> 
</ng-container> 

代碼應該輸出<div>這樣的:

<div my-component></div> 

但它不是,我得到這個錯誤:

DOMException: Failed to execute 'setAttribute' on 'Element' 

如果我只是在div標籤內打印值,效果很好:

<div>{{component.name}}</div> 

它甚至有可能實現我想要的嗎?

+0

如何生成自定義組件標籤,如:'<{{component.name}}>' – Jai

+0

'

'試試這個? – Jai

+0

@Jai,謝謝,但他們都沒有工作。 – igasparetto

回答

2

您可以創建一個組件工廠,把那些你需要作爲入口部件組成:

件廠查看

<div #dynamicComponentContainer></div> 

件廠控制器

import { Component,Input,ViewContainerRef,ViewChild,ReflectiveInjector,ComponentFactoryResolver } from '@angular/core'; 

import { YourComponent } from './your-component.component'; 

@Component({ 
    selector: 'component-factory', 
    templateUrl: './component-factory.component.html', 
    styleUrls: ['./component-factory.component.css'], 
    entryComponents: [ YourComponent ] 
}) 

export class ComponentFactoryComponent { 

currentComponent = null; 

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

// component: Class for the component you want to create 
// inputs: An object with key/value pairs mapped to input name/input value 
    @Input() set componentData (data: {component: any, inputs: any }) {+ if  (!data) { 
    return; 
} 

// Give you access to the inputs inside the component 
let inputProviders = Object.keys(data.inputs).map((inputName) => {return {provide: inputName, useValue: data.inputs[inputName]};}); 
let resolvedInputs = ReflectiveInjector.resolve(inputProviders); 

// This will prepare the inject of inputs on the factory 
let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.dynamicComponentContainer.parentInjector); 

// Creates a factory 
let factory = this.resolver.resolveComponentFactory(data.component); 

// Here we inject the inputs on the factory 
let component = factory.create(injector); 

// This will add the component in the DOM container 
this.dynamicComponentContainer.insert(component.hostView); 

// This destroys the old component and input the new one 
if (this.currentComponent) { 
    this.currentComponent.destroy();+ } 

this.currentComponent = component; 
} 

constructor(private resolver: ComponentFactoryResolver) { } 

在組件您想要使用您需要提供的輸入,我們通過噴油器完成:

組件要使用

import { Component, Input, Injector } from '@angular/core'; 

@Component({ 
    selector: 'your-component, [your-component]', 
    templateUrl: './your-component.component.html', 
    styleUrls: ['./your-component.component.css'] 
}) 
export class YourComponent { 
    @Input() name: string; 
    @Input() label: string; 
    @Input() value: string; 

    constructor(private injector: Injector) { 
    this.name = this.injector.get('name'); 
    this.label = this.injector.get('label'); 
    this.value = this.injector.get('value'); 
    } 
} 

然後你的應用程序組件上,或當你想使用它:

應用程序組件視圖

<component-factory [componentData]="componentData"></component-factory> 

應用組件控制器

import { Component } from '@angular/core'; 
import {YourComponent} from './your-component.component' 

@Component({ 
    selector: 'app', 
    templateUrl: './app.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 

    componentData = null; 

    constructor() { } 

    ngOnInit() { 
    this.componentData = { 
     component: YourComponent, 
     inputs: { 
     name: 'example', 
     label: 'John Doe', 
     value: 'foo' 
    } 
    } 
} 
}