Angular Configuration

In Previous topic we have seen about Angular Observable, in this topic we will look into configuration part of our angular application. 
When an application starts it need some sort of runtime configuration information like UR endpoint etc.
 
APP_INITIALIZER ➤➤➤

APP_INITIALIZER is a dependency injection token that you can use to provide one or more initialization functions. The provided functions are injected at application startup and executed during app initialization. If any of these function returns a Promise or Observable, initialization does not complete until the promise is resolved or Observable is completed. 

We will look into an example in which we will get some results, these results usually returned as an observable or a promise which matches exactly with the signature of APP_INITIALIZER function. So to use this service we do not need to create any new instance like

Service service = new Service();

Angular will handle these through dependency injection, we only need to declare our dependency in the deps array when providing APP_INITIALIZER token.

Code will look as shown below in app.module.ts

providers: [
    {
      provide : APP_INITIALIZER,
      useFactory : (envConfigService : ConfigService) => () =>envConfigService.load().toPromise(),
      deps : [ConfigService],
      multi : true
    }
  ],

We need to execute envConfigService.load(). We cannot do it directly from the provider. we have to create a function which invokes envConfigService.load() and return a promise.

The useFactory is used because we are using a function and Angular Injector executes the function which in turn calls envConfigService.load().
The Angular Dependency Injection injects dependencies to classes & components but not to function but our function need ConfigService to be injected as the argument. We do that by deps flag and we will let angular know that we need to create a instance of ConfigService.

Also if you look at the definition of useFactory it say " A function to invoke to create a value for this token. The function is invoked with resolved values of token in the deps field."

The multi : true will create multi provider DI token which means you can provide array of providers for a DI token.

If multi : false (this is by default configuration) which means you can have only on provider for token. the last to register will override all the previous token.

Below are the code for Config Service, I have created this in environment.ts as it will load the API URL's at startup of application.

import { Injectable } from "@angular/core";
import { Observable, shareReplay } from "rxjs";
import { HttpClient, HttpBackend } from '@angular/common/http';

export const environment = {
  production: false
};

export class Configuration {
  userLogin : string = '';
  envName : String = '';
}

export class EnvironmentConstants {
  public static userLogin : string;
  public static userRegistration: string;
  public static envName : String;
  public static getNotification : string;
}
@Injectable(
  {providedIn:'root'})
export class ConfigService {

  private readonly envJson = '../assets/Environment.json'; // This contains API URL's

  private config$ : Observable<Configuration>|any;
  constructor(private handler : HttpBackend) {}
  public load() : Observable<Configuration> {

    const client = new HttpClient(this.handler);
    console.log(this.config$);

    if(!this.config$) {
      this.config$ = client.get<Configuration>(`${this.envJson}`).pipe(shareReplay(1));
      console.log(this.envJson);
      this.config$.subscribe({
        next : (envData: { [x: string]: any; }) => {
          if(envData && envData[`status`].toLowerCase() === 'success'){
            const data = envData['data'];
            EnvironmentConstants.envName = data.envName;
            EnvironmentConstants.userLogin = data.userLogin;
            EnvironmentConstants.userRegistration = data.userRegistration;
            EnvironmentConstants.getNotification = data.getNotification;
          }
          else {
            window.alert('Error')
          }
        }
    })
    }
    return this.config$
  }
}

Now if you start your service then you can in network tab that Environment.json file is called and it contains api details as shown below



In short you can say that APP_INITIALIZER is an instance of InjectionToken. It allow us to hook into the Angular Initialization process and run our custom logic.




Comments

Popular posts from this blog

Introduction to Angular

Bootstrap in Angular

Angular Directives