w00ter
w00ter

Reputation: 38

Injecting configuration object into library

I am building an angular library and consuming it in an angular app. (Both the angular library and app are built in angular v.13) The angular library holds a service that needs a configuration object to get some parameters.

This setup seems to work when I don't use a certain configuration, just 'ng serve'. But, when using a configuration like 'ng serve -c dev', it gives me this error :

Error: NG0204: Can't resolve all parameters for AzureWebmetricsService: (?).
    at getUndecoratedInjectableFactory (core.mjs:11506:1)
    at injectableDefOrInjectorDefFactory (core.mjs:11496:1)
    at providerToFactory (core.mjs:11539:1)
    at providerToRecord (core.mjs:11526:1)
    at R3Injector.processProvider (core.mjs:11429:1)
    at core.mjs:11402:1
    at core.mjs:4162:1
    at Array.forEach (<anonymous>)
    at deepForEach (core.mjs:4162:1)
    at R3Injector.processInjectorType (core.mjs:11402:1)

Here is the code :

App.module.ts

@NgModule({
  imports: [
    ...
    WebmetricsModule.forRoot({ instrumentationKey : "bla"})
 ],
 ...

Configuration.model.ts

export class Configuration {
  public instrumentationKey: string;

  constructor() {
    this.instrumentationKey = '';
  }

}

dependencyinjection.ts

export const AZURE_WEB_METRICS_CONFIG = new InjectionToken<Configuration>('azure.web_metrics.config');

Webmetrics.module.ts

@NgModule({
  declarations: [
  ],
  imports: [
  ],
  exports: [
  ],
  providers: [
  ]
})
export class WebmetricsModule {

  static forRoot(configuration : Configuration): ModuleWithProviders<WebmetricsModule> {
    return {
      ngModule: WebmetricsModule,
      providers: [
        AzureWebmetricsService,
        {provide: AZURE_WEB_METRICS_CONFIG, useValue: configuration}
      ]
    };
  }
}

Azurewebmetrics.service.ts


export class AzureWebmetricsService {

  appInsights : ApplicationInsights;

  constructor(@Inject(AZURE_WEB_METRICS_CONFIG) private readonly config : Configuration) {
    this.appInsights = new ApplicationInsights({
      config: {
        instrumentationKey: config.instrumentationKey,
        enableAutoRouteTracking: true // option to log all route changes
      }
    });
    this.appInsights.loadAppInsights();
  }
}

Upvotes: 0

Views: 889

Answers (2)

w00ter
w00ter

Reputation: 38

After implementing the InjectionToken, I needed to adjust the "lib" version in the tsconfig.json of my app. The library I built had the setting on "es2020" and my app "es2018". Changing that in the app to "es2020" made it work.. which I think is kind of strange.

Upvotes: 0

Salketer
Salketer

Reputation: 15711

You should be using an injection token.

export const AZURE_WEB_METRICS_CONFIG = new InjectionToken<Configuration>('azure.web_metrics.config');

Use it to declare the provider in your module definition

@NgModule({
  declarations: [
  ],
  imports: [
  ],
  exports: [
  ],
  providers: [
  ]
})
export class WebmetricsModule {

  static forRoot(configuration : Configuration): ModuleWithProviders<WebmetricsModule> {
    return {
      ngModule: WebmetricsModule,
      providers: [
        AzureWebmetricsService,
        {provide: , useValue: configuration}
      ]
    };
  }
}

Then use it in the dependency.

export class AzureWebmetricsService {

  appInsights : ApplicationInsights;

  constructor(@Inject(AZURE_WEB_METRICS_CONFIG) config : Configuration) {
    this.appInsights = new ApplicationInsights({
      config: {
        instrumentationKey: config.instrumentationKey,
        enableAutoRouteTracking: true // option to log all route changes
      }
    });
    this.appInsights.loadAppInsights();
  }
}

Upvotes: 1

Related Questions