Error when trying to use a service in dynamically created component angular 5.1

不羁的心 提交于 2019-12-21 21:53:59

问题


When trying to use a service in dynamically created component We got this error at run time

ERROR Error: Can't resolve all parameters for class_1: (?). at syntaxError (compiler.js:485) at CompileMetadataResolver._getDependenciesMetadata (compiler.js:15664) at CompileMetadataResolver._getTypeMetadata (compiler.js:15499) at CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:15007) at CompileMetadataResolver.loadDirectiveMetadata (compiler.js:14862) at eval (compiler.js:34233) at Array.forEach () at eval (compiler.js:34232) at Array.forEach () at JitCompiler._loadModules (compiler.js:34229)

here is a sample code

  import { Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef, OnInit, ViewContainerRef } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { RouterModule } from '@angular/router';
    import { CmsService } from "../../services/cms.service";

    @Component({
      selector: 'home-page',
      template: `
          <ng-container #vc></ng-container>
      `
    })

    export class HomePageComponent implements OnInit {
      constructor(private _compiler: Compiler, private _injector: Injector, private _m: NgModuleRef<any>) { }
      ngOnInit() {

      }
      @ViewChild('vc', { read: ViewContainerRef }) vc;
      ngAfterViewInit() {
        const tmpCmp = Component({ moduleId: module.id, templateUrl: '../../../assets/HomePage/home-page-rbu.component.html' })(
          class {
            constructor(public cms: CmsService) { }
            welcomeTXT: string;
            advertismentTXT: string;
            ngOnInit() {
              this.cms.getCMSItemValue('welcomeTXT').subscribe(res => {
                this.welcomeTXT = res;
              });
              this.cms.getCMSItemValue('advertismentTXT').subscribe(res => {
                this.advertismentTXT = res;
              });

            }
          });

        @NgModule({
          imports: [BrowserModule, RouterModule],
          declarations: [tmpCmp],
          providers: [CmsService]
        })
        class DynamicModule { }

        this._compiler.compileModuleAndAllComponentsAsync(DynamicModule)
          .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);
          })
      }
    }

this sample code was working fine before adding CmsService or any angular service we are using angular 5.1 and angular-cli 1.5


回答1:


Workaround for the issue is to access the public properties of the dynamic created componenet using the componentFactories

welcomeTXT: string;
advertismentTXT: string;

as:

this._compiler.compileModuleAndAllComponentsAsync(DynamicModule)
  .then((factories) => {
    const f = factories.componentFactories[0];

    const cmpRef = f.create(this._injector, [], null, this._m);
    cmpRef.instance.welcomeTXT = _welcomeTXT;
    cmpRef.instance.advertismentTXT = _advertismentTXT;
    cmpRef.instance.visitorsCount = _visitorsCount;
    cmpRef.instance.name = 'dynamic';
    this.vc.insert(cmpRef.hostView);
  })

And here is the full code for the component:

import {  Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef, OnInit,  ViewContainerRef} from '@angular/core';
import { BrowserModule, DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { CmsService } from "../../services/cms.service";

@Component({
  selector: 'my-app',
  template: `
      <ng-container #vc></ng-container>
  `
})
export class HomePageComponent implements OnInit {
  @ViewChild('vc', { read: ViewContainerRef }) vc;

  constructor(private _compiler: Compiler, private _cms: CmsService, private _injector: Injector, private _m: NgModuleRef<any>, private sanitizer: DomSanitizer) { }
  ngOnInit() {

  }

  ngAfterViewInit() {
    let welcomeTXT: any = "";
    let advertismentTXT: any = "";
    let visitorsCount: number = 0;
    this._cms.getVisitorsCount().subscribe(res => {
      visitorsCount = res;
    });
    this._cms.getCMSItemValue('welcomeTXT').subscribe(res => {
      advertismentTXT = this.sanitizer.bypassSecurityTrustHtml(res);
      this._cms.getCMSItemValue('advertismentTEXT').subscribe(res => {
        welcomeTXT = this.sanitizer.bypassSecurityTrustHtml(res);
        this.CreateHomePageComponent(welcomeTXT, advertismentTXT, visitorsCount);
      });
    });
  }

  CreateHomePageComponent(_welcomeTXT: any, _advertismentTXT: any, _visitorsCount: number) {

    const tmpCmp = Component({ moduleId: module.id, templateUrl: '../../../assets/HomePage/home-page-rbu.component.html' })(
      class {
        welcomeTXT: string;
        advertismentTXT: string;
        visitorsCount: number = 0;
      });

    @NgModule({
      imports: [BrowserModule, RouterModule],
      declarations: [tmpCmp],
      providers: [CmsService]
    })
    class DynamicModule { }

    this._compiler.compileModuleAndAllComponentsAsync(DynamicModule)
      .then((factories) => {
        const f = factories.componentFactories[0];

        const cmpRef = f.create(this._injector, [], null, this._m);
        cmpRef.instance.welcomeTXT = _welcomeTXT;
        cmpRef.instance.advertismentTXT = _advertismentTXT;
        cmpRef.instance.visitorsCount = _visitorsCount;
        cmpRef.instance.name = 'dynamic';
        this.vc.insert(cmpRef.hostView);
      })
  }
}

I wish this help someone

We can also pass the service as variable like visitorsCount



来源:https://stackoverflow.com/questions/47789613/error-when-trying-to-use-a-service-in-dynamically-created-component-angular-5-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!