damola
damola

Reputation: 292

Angular 4 different token same Implemetation

I have an angular 4 app that is broken down into different feature. So I have a shopping feature with all its components and billing feature with all its component.

However, I have an issue with configuration. I would like to share configuration between multiple feature of the app. My configuration is different for each feature so I created a base config class and inherit from it.

However in my app.module is did a registration such as below.

{ provide: BillingModuleConfig, useClass: ConfigService },
{ provide: ShoppingConfig, useClass: ConfigService }
{
  provide: APP_INITIALIZER,
  useFactory: configServiceFactory,
  deps: [ShoppingConfig],
  multi: true
}

However, this does not work for the BillingModuleConfig. Which implies when I inject BIllingConfig in the section I need it from I cannot get the config setting. Is there a reason why this would not work? My ConfigServiceFactory is the an external function that load the config file as below.

export function configServiceFactory(config: ConfigService) {
  return () => config.load();
}

The config.load method loads all the configuration into a class that inherits from both ShoppingConfig and BillingConfig.

The config.load implementation is

import { Injectable, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { BillingModuleConfig} from '@razor/Billing';
import { ShoppingConfig } from '@razor/shopping';
import { environment } from './../../environments/environment';
import { HttpClient } from '@angular/common/http';

abstract class Settings implements BillingModuleConfig, ShoppingConfig {
 public ShoppingAPIUrl: string;
  public BillingApiUrl: string;

}

@Injectable()
export class ConfigService implements Settings {

  constructor(private http: HttpClient) {}

  public load() {
    return new Promise((resolve, reject) => {
      this.http
        .get<Settings>(environment.configFileName)
        .subscribe((config: AppSettings) => {
          this.ShoppingAPIUrl= config.ShoppingAPIUrl;
          this.BillingApiUrl= config.BillingApiUrl;
          resolve(true);
        });
    });
  }
}

Upvotes: 1

Views: 48

Answers (1)

Estus Flask
Estus Flask

Reputation: 223054

Considering that config.load assigns fetched configuration to ConfigService class instance, it will work only for provider token that was specified as a dependency for APP_INITIALIZER, which is ShoppingConfig.

In order for the configuration to be fetched in BillingModuleConfig, it should be specified, too:

{
  provide: APP_INITIALIZER,
  useFactory: configServiceFactory,
  deps: [ShoppingConfig],
  multi: true
},
{
  provide: APP_INITIALIZER,
  useFactory: configServiceFactory,
  deps: [BillingModuleConfig],
  multi: true
}

However, this will result in two requests. To avoid this, the most simple way is to use ConfigService everywhere. If BillingModuleConfig and ShoppingConfig were introduced because the configuration is currently combined but supposed to be divided later, they can reuse a common instance:

ConfigService,
{ provide: BillingModuleConfig, useExisting: ConfigService },
{ provide: ShoppingConfig, useExisting: ConfigService },
{
  provide: APP_INITIALIZER,
  useFactory: configServiceFactory,
  deps: [ConfigService],
  multi: true
}

Upvotes: 1

Related Questions