angular - 用于生成动态组件的通用函数
我想在我的服务中编写一个函数,用于处理生成动态组件到某个 ViewChild 引用中……
我尽力了
public GenerateDynamicComponent(ComponentName: string,viewContainerRef: ViewContainerRef, data?: any) {
switch (ComponentName.toUpperCase()) {
case 'DYNAMICFORMS':
const componentFactory = this.resolver.resolveComponentFactory(DynamicFormsComponent);
const formref = viewContainerRef.createComponent(componentFactory);
formref.instance.Data = data;
return formref;
break;
default:
return null;
}
它确实工作得很好,但我不想使用这个开关并通过字符串发送这个组件名
所以它需要像
public GenerateDynamicComponent<T>(viewContainerRef: ViewContainerRef,data?: any ) {
const componentFactory = this.resolver.resolveComponentFactory<T>(typeof T);
const formref = viewContainerRef.createComponent(componentFactory);
formref.instance.Data = data;
return formref;
}
但是当然这不起作用,因为 typeof T <> 组件类型……是否有可能这样做,还是必须像第一个例子那样?
非常感谢!
答案#1
可以将创建动态组件的通用函数定义如下。
public createDynamicComponent<T>(component: Type<T>, viewRef: ViewContainerRef): ComponentRef<T> {
const factory = this.cfr.resolveComponentFactory<T>(component);
return viewRef.createComponent(factory);
}
并且调用通用函数...
this.createDynamicComponent<DynamicComponent>(DynamicComponent, this.vc /* ViewContainerRef */);
查看 Stackblitz 示例应用。
注意:确保在模块中将动态组件添加到 entryComponents
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DynamicComponent } from './dynamic.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
完整组件上下文
import {
AfterViewInit, Component, ComponentFactoryResolver, ComponentRef, Type, ViewChild, ViewContainerRef
} from '@angular/core'
import { DynamicComponent } from './dynamic.component'
@Component({
selector: 'my-app',
template: `
<h1>App component</h1>
<div class="insert-dynamic-component">
<ng-container #vc></ng-container>
</div>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
@ViewChild('vc', {read: ViewContainerRef, static: false}) vc: ViewContainerRef;
public constructor(private cfr: ComponentFactoryResolver) {}
ngAfterViewInit() {
// setTimeout() to prevent error "Expression has changed after it was checked"
// See: https://blog.angular-university.io/angular-debugging/
setTimeout(() => {
const componentRef: ComponentRef<DynamicComponent> =
this.createDynamicComponent<DynamicComponent>(DynamicComponent, this.vc);
componentRef.instance.data = 'New data';
});
}
public createDynamicComponent<T>(component: Type<T>, viewRef: ViewContainerRef): ComponentRef<T> {
const factory = this.cfr.resolveComponentFactory<T>(component);
return viewRef.createComponent(factory);
}
}
DynamicComponent
import { Component } from '@angular/core';
@Component({
selector: 'dynamic-component',
template: `<h1>Dynamic Component!</h1>
<p>Data: {{data}}</p>`,
styles: [`h1 { font-family: Lato; }`]
})
export class DynamicComponent {
public data: any
}
