I am testing a Highcharts Angular2x Wrapper. At first, I had no problem using Angular CLI (1.6.1) "ng serve" and profiling performance with Chrome. Then, i tried to use ahead-of-time compiling to see how that affects the performance.
So, using:
ng serve --aot
I get the following error:
ERROR in Error during template compile of 'AppModule'
Function calls are not supported in decorators but 'ChartModule' was called.
Now, i know that aot generates factory code for modules and somehow "transformes" templates to VanillaJS, things get a bit tricky here and i couldn't understand how ngc is going to generate factory code for a module that requires an external library.
I got this App.Module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ChartModule } from 'angular2-highcharts';
import { AppComponent } from './app.component';
declare var require: any;
export function getHighchartsModule() {
return require('highcharts');
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ChartModule.forRoot(getHighchartsModule) // This causes the error
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
My Package.json dependencies :
"dependencies": {
"@angular/animations": "^5.0.0",
"@angular/common": "^5.0.0",
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
"@angular/http": "^5.0.0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/router": "^5.0.0",
"angular2-highcharts": "^0.5.5",
"core-js": "^2.4.1",
"rxjs": "^5.5.2",
"zone.js": "^0.8.14"
}
My questions are : Is there anything i can do here to avoid the mentioned compiling error ? Can anyone explain why does this happen ? (optional)
This is a problem with angular in general. Angular compiler wants the forRoot
code to be completely static.
As an example, in the following code even the assignment of the static variable will cause this error:
static forRoot(config: MyConfig): ModuleWithProviders {
MyConfigService.config = config;// This line with cause an error
return {
ngModule: HttpTrackerLibModule,
};
}
If you are not library creator there is nothing much you can do but try library-specific solutions like the one above. But if you are a library creator you can try a static approach as follows:
Create an injection token:
export const USER_OPTIONS = new InjectionToken<MyConfig>('USER_OPTIONS');
Provide the token in your library Module
static forRoot(config: MyConfig): ModuleWithProviders {
return {
ngModule: HttpTrackerLibModule,
providers: [{
provide: USER_OPTIONS,
useValue: config
}],
};
}
export class ConfigService {
constructor(@Inject(USER_OPTIONS) private _config: MyConfig) {
}
}
Mentioning the Github issue here. The following solution worked for me.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
// Angular Highcharts Imports
import {HighchartsStatic} from 'angular2-highcharts/dist/HighchartsService';
import { ChartModule } from 'angular2-highcharts';
// Factory Function
export function highchartsFactory() {
var hc = require('highcharts');
return hc;
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ChartModule // Import Module Here
],
providers: [ // Provide Service Here
{
provide: HighchartsStatic,
useFactory: highchartsFactory
},
],
bootstrap: [AppComponent]
})
export class AppModule { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With