In this tutorial, we’ll explore how to use APP_INITIALIZER provider in Angular through the dependency injection system to load configuration data for both development and production environments.
We’ll create a service that loads configuration data from a file, use APP_INITIALIZER to ensure that the data is loaded before the application starts, and provide the data to our components using dependency injection system.
Introduction
Before running a web application, it is often necessary to load some configuration data.
This might could include API endpoints, feature flags, or other settings that differ depending on whether the application is in development or production mode.
We can use the APP_INITIALIZER provider in angular to perform initialization tasks before the application starts running.
This allows us to ensure that any necessary configuration data is loaded and available before the application starts rendering.
Additionally, we can use Angular’s powerful dependency injection system to provide the results of these initialization tasks to our components and services.
This makes it easy to access configuration data and other initialization results from anywhere in our application.
What is APP_INITIALIZER provider in angular ?
“APP INITIALIZER” is an Angular provider token that allows you to execute code before the application is fully bootstrapped.
It is used to complete some initialization activities that must be completed before the program can run.
The actions taken with “APP INITIALIZER” can be anything that needs to be done before the application launches, such as retrieving configuration information from a server or starting a logging service.
How does APP_INITIALIZER relate to dependency injection?
In Angular, dependency injection is used to provide services to components and other parts of the application.
When you inject a service into a component or other object, Angular creates an instance of that service and provides it to the object.
“APP_INITIALIZER” can be used in conjunction with dependency injection to perform some initialization tasks before the application starts, and to provide the results of those tasks to other parts of the application.
How to use APP_INITIALIZER provider ?
Let’s explore how to use APP_INITIALIZER
with a simple example.
Imagine you have two API environments, one for production and one for development, and you want to use the appropriate configuration file based on the environment before running your application.
- Create two configuration files, one for development and one for production, and store them in a folder called “assets”. For example, create files named “
config.dev.json
” and “config.prod.json
“ - Create a service that loads the appropriate configuration file based on the environment. The service should be injected with the Angular
HttpClient
service to make HTTP requests to load the configuration files
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ConfigService {
private config: any;
constructor(private http: HttpClient) { }
loadConfig(): Promise {
const configFile = environment.production ? 'config.prod.json' : 'config.dev.json';
return this.http.get(`/assets/${configFile}`).toPromise().then(config => {
this.config = config;
});
}
getConfig(): any {
return this.config;
}
}
In this example, we inject the HttpClient
service into the ConfigService
and use it to load the appropriate configuration file based on the environment.
We store the loaded configuration data in a private variable called config
.
- In your app module, provide the
ConfigService
usingAPP_INITIALIZER
and call theloadConfig
method:
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ConfigService } from './config.service';
function initConfig(configService: ConfigService) {
return () => configService.loadConfig();
}
@NgModule({
imports: [
HttpClientModule,
// Other imports here
],
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: initConfig,
deps: [ConfigService],
multi: true
}
],
// Other module configuration here
})
export class AppModule { }
In this example, we define a function called initConfig
that takes a ConfigService
instance as a dependency.
We then return a function that calls the loadConfig
method of the ConfigService
instance.
We then provide this function to APP_INITIALIZER using the useFactory
property in our app module.
Furthermore, we also include the ConfigService
instance as a dependency using the deps
property.
- In your component, inject the
ConfigService
and use thegetConfig
method to access the configuration data:
import { Component } from '@angular/core';
import { ConfigService } from './config.service';
@Component({
selector: 'app-root',
template: `
{{ title }}
API endpoint: {{ config.apiEndpoint }}
`
})
export class AppComponent {
title = 'XperTuto.com';
config: any;
constructor(configService: ConfigService) {
this.config = configService.getConfig();
}
}
In this component, we inject the ConfigService
and use the getConfig
method to access the configuration data.
We can then use this data to display information in our template.
By using APP_INITIALIZER
and dependency injection in this way, we ensure that the appropriate configuration file is loaded based on the environment, and that the configuration data is available before the component is initialized.
References and Links
Here are more related references and links that discuss the same subject:
- Angular Documentation
- Dependency injection in Angular
- How to use Services in Angular ?
- How to use Providers in Angular ?
- Using Injector , @Injectable & @Inject in Angular
- How to create a singleton service in Angular ?
- Using provideIn root , any & platform in Angular ?
- How to use ViewProviders in Angular ?
- Using @Self , @SkipSelf & Optional Decorators in Angular
- How to use APP_INITIALIZER provider in Angular ?