In the previous article, we introduced the useClass property within the providers array to define how the Angular Dependency Injection system instantiates a class. In this article, we will delve deeper into this syntax and explore providers in Angular.
Before we proceed, let's refresh our memory 😁 .
In Angular, providers are an array of instructions, where each provider is an instruction or recipe that describes how an object for a particular class, string, token, etc., is created.
Now, let's focus on a specific object in the providers array:
{ provide: LoggerService, useClass: LoggerService }
This Provider object contains two properties: provide and useClass.
The provide property represents the identifier of the provider, which can be either a string or an instance of InjectionToken. In our example
Contructor(public loggerService:LoggerService)
we inject an instance of LoggerService into a component's constructor using LoggerService as the token 🥴🥴.
If this isn't clear, don't worry; examples will help you understand it better 😉.
Consider the following modified provider syntax:
providers: [
{ provide: LoggerService, useClass: BetterProductService }
]
Now, when Angular encounters the need to inject LoggerService in a constructor, it will search the providers and find LoggerService. However, instead of injecting LoggerService, it will inject BetterProductService. In other words, the provide: LoggerService is merely a token used to identify what we want to inject.
For your Information :
Angular doesn't complain if the token is used multiple times. In the following example, the token LoggerService is used twice, but the last registration (BetterProductService) takes precedence.
providers: [
{ provide: LoggerService, useClass: LoggerService },
{ provide: LoggerService, useClass: BetterProductService }
]
*You should also know that the token can also be a string ! *
For example:
providers: [{ provide: 'LoggerService', useClass: LoggerService }]
In this case, 'LoggerService' serves as a string token. To inject LoggerService, we can use the @Inject decorator as shown below:
export class AppComponent {
constructor(@Inject('LoggerService') private loggerService: LoggerService) {}
}
However, using string tokens can introduce naming collisions if multiple parts of your application use the same string for different purposes. This can lead to conflicts and make your code harder to understand.
To address this, Angular provides the InjectionToken
What is an Injection Token?
An Injection Token is similar to a string token, but instead of using a hardcoded string, we create the Injection Token by instantiating the InjectionToken class. This ensures that the tokens are always unique.
To create an Injection Token, import InjectionToken from @angular/core:
import { InjectionToken } from '@angular/core';
Next, create a new instance of InjectionToken with a unique name, such as LoggerServiceToken:
export const LoggerServiceToken = new InjectionToken<string>('LoggerService');
Here, we specify the optional type parameter and the token description, which helps clarify the token's purpose.
Register the Injection Token in the providers array:
providers: [
{ provide: LoggerServiceToken, useClass: LoggerService },
// Other providers...
]
Now, you can inject the LoggerService using the Injection Token in your component:
export class AppComponent {
constructor(@Inject(LoggerServiceToken) public loggerService: LoggerService) {}
In the next article, we will explore additional properties of the provider object in Angular. Apart from provide, there are other properties that can be used to configure the dependency injection behavior.
Top comments (1)
Great article, Congratulations! Do you have a use case where you use InjectionToken?