问题
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