Angular,在运行时编译和创建组件

Angular, compile and create components at runtime

我正在尝试在 angular 中制作一个文档生成工具,但我遇到了如何允许用户动态创建内容的挑战。

我想创建的组件可能具有任意模型和行为,所以我认为我无法使用共享组件。

我描述的组件在编译时不存在。

我看到一些 documentation for rendering dynamic components。但是它提到您必须在 ngModule 中的 entryComponents 中列出 "dynamic" 组件。 对我的情况无效。

Is there another mechanism to get this effect?

您可以即时创建模块和组件,对其应用装饰器,然后全部编译。然后你就可以访问编译好的组件了:

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

constructor(private _compiler: Compiler,
            private _injector: Injector,
            private _m: NgModuleRef<any>) {
}

ngAfterViewInit() {
  const template = '<span>generated on the fly: {{name}}</span>';

  const tmpCmp = Component({template: template})(class {
  });
  const tmpModule = NgModule({declarations: [tmpCmp]})(class {
  });

  this._compiler.compileModuleAndAllComponentsAsync(tmpModule)
    .then((factories) => {
      const f = factories.componentFactories[0];
      const cmpRef = f.create(this._injector, [], null, this._m);
      cmpRef.instance.name = 'dynamic';
      this.vc.insert(cmpRef.hostView);
    })
}

要使这种方法起作用,您需要将编译器引入运行时。有关动态组件的更多详细信息,请阅读文章:

我找到了适用于 Angular 13 的解决方案,并希望与您分享。

const importedFile = await import('pathToModule');
const module: NgModuleRef<E> = createNgModuleRef<E>(importedFile[moduleClassName], this._injector);
this.containerRef.createComponent(importedFile[componentClassName], { ngModuleRef: module });

在 Angular 13 中,Compiler 被贬低了。整个编译过程都是在幕后完成的,即使我们动态导入一些 module/component.

我的解决方案需要在导入的模块文件中添加我们要创建的组件的导出。

export * from './containers/container.component';

** 您可以动态创建组件和模块而不是导入文件(如上面的示例),而不是编译器只使用 createNgModuleRefcreateComponent 函数 **