angularangular-componentsangular-compilerangular-dynamic-components

Angular: How to use shared modules in a Dynamic Component?


I'm creating dynamic component in Angular v6 using compileModuleAndAllComponentsAsync of angular compiler with same below code.

viewChangeMethod(view: string) {
    let template = `<span>${view} </span>`;
    const tmpCmp = Component({ template: template })(class { });
    this._compiler.clearCacheFor(this.tmpModule)
    this.tmpModule = NgModule({ declarations: [tmpCmp,FRAComponent],import:[ComonModule] })(class {
    });

    this._compiler.compileModuleAndAllComponentsAsync(this.tmpModule)
        .then((factories) => {
            const f = factories.componentFactories[0];
            const cmpRef = f.create(this._injector, [], null, this._m);
            this._container.detach()
            console.log(cmpRef.hostView)
            this._container.insert(cmpRef.hostView);
        })
    this._compiler.clearCacheFor(this.tmpModule)
}

Every thing is working fine but when importing any shared module or custom module below error.

enter image description here


Solution

  • If you will be requiring shared modules or any additional modules for you Dynamic Component I recommend you take a slightly different approach to creating you Dynamic Component.

    My projects use dynamic components and I also import various modules into them, but I've used the following approach to creating my components - Full working StackBlitz

    Above is a StackBlitz example I created if you want to adjust that to your needs || below is a copy of the code.

    import {
      Component, ViewChild, AfterContentInit, ComponentFactoryResolver,
      Compiler, ViewContainerRef, NgModule, NgModuleRef
    } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    
    @Component({
      selector: 'app',
      template: '<ng-template #vc></ng-template>',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements AfterContentInit {
      @ViewChild('vc', { read: ViewContainerRef }) _container: ViewContainerRef;
      private cmpRef;
    
      constructor(
        private componentFactoryResolver: ComponentFactoryResolver,
        private compiler: Compiler,
        private _m: NgModuleRef<any>) { }
    
    
      ngAfterContentInit() {
        this.addComponent();
      }
    
      public sayHello(): void{
        alert("Hello!");
      }
    
      private addComponent(): void {
        @Component({
          template: `<h2>This is a dynamic component</h2>
          <button (click)="_parent.sayHello()">Click me!</button>`
        })
        class DynamicComponent {
          constructor(public _parent: AppComponent) { }
        }
        @NgModule({
          imports: [
            BrowserModule
          ],
          declarations: [DynamicComponent],
        }) class DynamicModule { }
    
        const mod = this.compiler.compileModuleAndAllComponentsSync(DynamicModule);
        const factory = mod.componentFactories.find((comp) =>
          comp.componentType === DynamicComponent
        );
        this.cmpRef = this._container.createComponent(factory);
      }
    
    }