angluar动态生成html组件
在使用angular
框架时,我们有时候需要根据动态的html
模板内容渲染组件。如果你是直接DomSanitizer
类生成安全的html
再绑定到[innerHTML]
属性,当你的html
包含一些angluar
组件时,它是不会进行渲染的这时候我们就需要根据html
内容动态创建组件渲染。
通过这种方式你就可以处理服务端返回的html
或者自定义生成的html
进行动态渲染。使用这种有一个弊端就是在你发布上线时(也就是build)不用使用aot
方式进行构建。你必须使用以下命令去构建。
ng build --prod --aot=false --build-optimizer=false
创建组件
和正常创建组件没有什么区别,我们还是要定义Component
和Module
。只是把这段代码封底装成一个函数。你也可以在组件里面定义@input
,Module
里面导入其它的模块。
export async function createComponentFactory(compiler: Compiler, template: string): Promise<ComponentFactory<any>> {
// const cmpClass = class DynamicComponent {};
@Component({
selector: 'dynamic-selector',
template: template,
}) class DynamicComponent {
@Input() settings;
@Input() source;
}
// IMPORT ALL MODULES HERE!!!
@NgModule({ imports: [
CommonModule,
RouterModule,
ThemeModule,
Ng2SmartTableModule,
/* All other modules including components that can be use with renderer */
],
declarations: [DynamicComponent] })
class DynamicHtmlModule {}
const moduleWithComponentFactory = await compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule);
return moduleWithComponentFactory.componentFactories.find(x => x.componentType === DynamicComponent);
}
这段代码就是定义一个组件模块,使用解释器编译这个模块。所以必须提供解释器类。
定义ViewContainerRef
我们需要定义一个ViewContainerRef
来容器来填充组件。
<ng-template #ref></ng-template>
@ViewChildren("ref", { read: ViewContainerRef}) public dynComponents: QueryList<ViewContainerRef>;
调用渲染
在调用的组件中你需要注入Compiler
。
protected createComponent(ref: ViewContainerRef, card: {[key:string]:any}) {
createComponentFactory(this.compiler, card["body"]).then(factory => {
const injector = Injector.create({ providers: [], parent: ref.injector });
const cmpRef = ref.createComponent(factory, 0, injector, []);
if (card["type"] == "table") {
// @ts-ignore
cmpRef.instance.settings = card["data"]["settings"];
cmpRef.instance.source = new LocalDataSource(card["data"]["data"]);
}
this.cmpRef.push(cmpRef);
});
}