How to compile runtime-generated Angular8 code?

前端 未结 1 640
没有蜡笔的小新
没有蜡笔的小新 2020-12-20 01:12

I\'m creating Angular code at runtime, in particular, I use a SVG library in order to create a vector graphic that contains Angular code directives like (click)=\'myMe

相关标签:
1条回答
  • 2020-12-20 01:51

    The JIT compiler is now excluded by default from AOT bundles so you have to include it manually. You need to install the package @angular/platform-browser-dynamic and add the Compiler providers to your application module. For example:

    import { NgModule, COMPILER_OPTIONS, CompilerFactory, Compiler } from '@angular/core';
    import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
    
    @NgModule({
      providers: [
        { provide: COMPILER_OPTIONS, useValue: {}, multi: true },
        { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
        { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
      ]
    })
    export class AppModule { }
    
    export function createCompiler(compilerFactory: CompilerFactory) {
      return compilerFactory.createCompiler();
    }
    

    Then you have to also make some small changes to your code because you cannot set the template to be a variable using the @Component decorator it gives a compile error. The decorator must be run dynamically in code.

    Here is your method updated with the changes:

    private addComponent(template: string) {
      class TemplateComponent {
    
        @ViewChild('target', {static: false, read: ViewContainerRef}) public target;
    
        constructor() {
        }
    
        public myMethod() {
          // do something     
        }
      }
    
      class TemplateModule {
        @ViewChild('target', {static: false, read: ViewContainerRef}) public target;
      }
    
      const componentType = Component({template: template + '<div #target></div>'})(TemplateComponent)
    
      const componentModuleType = NgModule({declarations: [componentType]})(TemplateModule)
    
      const mod = this.compiler.compileModuleAndAllComponentsSync(componentModuleType);
      const factory = mod.componentFactories.find((comp) =>
          comp.componentType === componentType
      );
      this.container.createComponent(factory);
    }
    

    I have created also a StackBlitz sample where you can see it working.

    For a more detailed sample on how to do this check this Angular AOT Dynamic Components GitHub repository with a full sample.

    I found this in the Angular GitHub issue about dynamically loading component templates. Since you use this it is probably good you follow the issue to be up to date on the developments.

    0 讨论(0)
提交回复
热议问题