Every app has some configurations to load. The most common is environment configurations which are required when you have multiple environments - local, dev, qa, uat and prod. Well this article will tell you where to store configurations and how to read them in Angular.
Let’s say we need to store the baseUrl of our app. Where do you think this should be added? There is a defined place for storing config in Angular and you should make most use of it. But before going to that let’s check out the wrong place to store the configs.
Wrong!
I know this comes as first option in our mind but can you see “config” in it’s name? No, right? Cause it was never meant to store configurations in this file. The sole purpose of this is to tell the run time what version of the code you want to run.
Now you may argue that we can create different environment.ts files for different versions, yes you can but again this is not the purpose of this file.
Then where to store your config?
One thing is certain that we need a static json file to store our configs so let’s first create a config file and name it config.json
. It will look something like this:
{
"baseUrl": "https://tutswiki.com/"
}
Now we have config.json
but we will need a place for it. One option is to have it in assets
or dist
and use it to get and set the configurations. But is this recommended? No!
So let’s move to our actual solution which is:
Sounds awesome right? It will specify a factory
and that will return a promise
, the promise
will load the config for the application. After loading the configs you can resolve the promise
.
Let’s take an example.
import { APP_INITIALIZER } from '@angular/core';
function initialize() {
return (): Promise<boolean> => {
return new Promise<boolean>((resolve: (a: boolean) => void): void => {
resolve(true);
});
};
@NgModule({
declarations: [
],
imports: [
],
providers: [{
provide: APP_INITIALIZER,
useFactory: initialize,
multi: true
}],
bootstrap: []
})
export class AppModule { }
useFactory
will have the function which will return a function which will return a promise.
multi: true
will allow to have multiple instances of the provider. They are all able to run simultaneously but the code will be stopped here until we get all the promises resolved.
In this code sample we have added APP_INITIALIZER
to app.module.ts
. It will call the initialize
method. You can use this method to load configurations and initialize your app. As told above, this will return a promise. You can replace resolve(true)
with your code or can write a new promise
.
To add dependencies, add a deps
section in its provider
. Example:
providers: [{
provide: APP_INITIALIZER,
useFactory: initialize,
deps: [
HttpClient,
UserInfoService,
ConfigService
],
multi: true
}],
and add them as parameter to our initialize
method.
function initialize(http: HttpClient, userInfoService: UserInfoService, config: ConfigService) {
return (): Promise<boolean> => {
return new Promise<boolean>((resolve: (a: boolean) => void): void => {
resolve(true);
});
};
First we will need a service to save the configs we are getting from config.json
so let’s create a ConfigService
.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ConfigService {
baseUrl: string;
constructor() { }
}
We have already added this in deps
of APP_INITIALIZER
.
Now let’s use initialize
method to read our config file and set the necessary details for our app.
function initialize(http: HttpClient, config: ConfigService): (() => Promise<boolean>) {
return (): Promise<boolean> => {
return new Promise<boolean>((resolve: (a: boolean) => void): void => {
http.get('./config.json')
.pipe(
map((x: ConfigService) => {
config.baseUrl = x.baseUrl;
resolve(true);
})
).subscribe();
});
};
}
And that’s how we deal with config in Angular.
Help us improve this content by editing this page on GitHub