13

The problem is that I'm calling a function inside forRoot method like this:

app.module.ts

import {environment} from '../environments/environment';

...

@NgModule({
  imports: [
    BrowserModule,
    MyModule.forRoot({
      config: {
        sentryURL: environment.SENTRY_URL <-- This, calls the function
      }
    }),
    HttpClientModule,
    ...
 ]})

environemnt.ts

export function loadJSON(filePath) {
  const json = loadTextFileAjaxSync(filePath, 'application/json');
  return JSON.parse(json);
}

export function loadTextFileAjaxSync(filePath, mimeType) {
  const xmlhttp = new XMLHttpRequest();
  xmlhttp.open('GET', filePath, false);
  if (mimeType != null) {
    if (xmlhttp.overrideMimeType) {
      xmlhttp.overrideMimeType(mimeType);
    }
  }
  xmlhttp.send();
  if (xmlhttp.status === 200) {
    return xmlhttp.responseText;
  } else {
    return null;
  }
}

export const environment = loadJSON('/assets/config.json');

And the config looks like this:

{
  "production": "false",
  "SENTRY_URL": "https://[email protected]/whatever/1"
}

When I do the build with aot, it says:

ERROR in src/app/app.module.ts(41,20): Error during template compile of 'AppModule' Function calls are not supported in decorators but 'loadJSON' was called in 'environment' 'environment' calls 'loadJSON'.

Any ideas??

:)

UPDATED SOLUTION:

My final solution is, in the app, use function getters as Suren Srapyan said. In the library, the forRoot method should look like this:

export const OPTIONS = new InjectionToken<string>('OPTIONS');

export interface MyModuleOptions {
  config: {
    sentryURLGetter: () => string | Promise<string>;
  }
}

export function initialize(options: any) {
  console.log('sentryURL', options.config.sentryURLGetter());
  return function () {
  };
}

@NgModule({
  imports: [
    CommonModule
  ]
})
export class MyModule {
  static forRoot(options: MyModuleOptions): ModuleWithProviders {
    return {
      ngModule: MyModule,
      providers: [
        {provide: OPTIONS, useValue: options},
        {
          provide: APP_INITIALIZER,
          useFactory: initialize,
          deps: [OPTIONS],
          multi: true
        }
      ]
    };
  }
}

:D

4
  • Nice. And what would be the parameter for forRoot() method ? Commented Feb 20, 2018 at 12:40
  • In my case the configuration of the module. Commented Feb 20, 2018 at 21:20
  • Can you provide a plunker with the updated solution ? Commented Oct 9, 2018 at 14:17
  • Not a plunker but the hole project, github.com/Ismaestro/angular6-example-app/blob/master/projects/… Commented Oct 9, 2018 at 15:25

1 Answer 1

9

Function call is not supported in the @Decorators. Alternative you can get the value outside @NgModule and than use it's value.

export function getSentryUrl() {
   return environment.SENTRY_URL;
}

@NgModule({
   imports: [
      BrowserModule,
      MyModule.forRoot({
      config: {
        getSentryURL: getSentryUrl
      }
    }),
    HttpClientModule,
    ...
 ]})
Sign up to request clarification or add additional context in comments.

1 Comment

I have updated. Try that way also. And in the forRoot call that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.