[英]Angular 2 dynamically create components in ngFor
My controller has a list of components I want to have inside a page. 我的控制器有一个我想要在页面中的组件列表。 Those other components are created and work correctly in isolation. 这些其他组件是独立创建和正常工作的。
In my HTML template: 在我的HTML模板中:
<ng-container *ngFor="let component of components">
<div {{component.name}}></div>
</ng-container>
The code should output a <div>
like this: 代码应该像这样输出一个<div>
:
<div my-component></div>
But it is not and I am getting this error: 但它不是,我收到这个错误:
DOMException: Failed to execute 'setAttribute' on 'Element'
It works well if I simply print the value inside the div tag: 如果我只是在div标签内打印值,它的效果很好:
<div>{{component.name}}</div>
Is it even possible to achieve what I want? 甚至有可能实现我想要的目标吗?
You can create a component factory and put those components that you need as an entry component: 您可以创建组件工厂并将您需要的那些组件作为条目组件:
<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) { }
On the component you want to use you'll need to provide the inputs, we do this by the Injector: 在您要使用的组件上,您需要提供输入,我们通过Injector执行此操作:
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');
}
}
Then on your app component, or whenever you want to use it: 然后在您的应用程序组件上,或者您想要使用它时:
<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'
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.