DEV Community

Cover image for Angular InjectionToken: Dependency Injection In-Depth
Cagkan Mert Oztas
Cagkan Mert Oztas

Posted on

Angular InjectionToken: Dependency Injection In-Depth

At first, I would like to thank Omer Incirkus, who helped me write this article and was with me while I was learning, for his contributions.


Dependency injection is a crucial concept in Angular that enables you to create loosely coupled components, services, and modules. With dependency injection, you can declare a service or component once and reuse it throughout your application, which makes your code more modular, testable, and maintainable.

Angular provides different ways to inject dependencies into your components, such as constructor injection. However, sometimes you may want to inject a value that is not a class or a service instance but rather a simple configuration value, such as a string, number, or boolean. In this case, you can use the InjectionToken class to define a token that represents the value you want to inject.

What is an InjectionToken in Angular?

An InjectionToken is a class in Angular that represents a unique identifier for a dependency. It provides a way to decouple the provider and the consumer of a dependency by allowing you to register a token with a provider and then inject the token into a consumer. The consumer can then use the token to retrieve the value of the dependency from the provider.

The InjectionToken class has a generic type parameter that specifies the type of the value that the token represents. For example, if you want to inject a string value, you can define an InjectionToken with a string type parameter:

import {InjectionToken} from '@angular/core';

export const MY_STRING_TOKEN = new InjectionToken<string>('my-string-token');
Enter fullscreen mode Exit fullscreen mode

In this example, we define an InjectionToken named ‘MY_STRING_TOKEN’ with a string type parameter. The first argument of the InjectionToken constructor is a string that provides a human-readable description of the token. This is optional, but recommended, as it helps with debugging and error reporting.

How to use an InjectionToken in Angular?

To use an InjectionToken, you need to register it as a provider in the module or component where you want to use it. You can do this by defining a provider with the token and the value that you want to inject:

import {Component, Inject, InjectionToken} from '@angular/core';

export const MY_STRING_TOKEN = new InjectionToken<string>('my-string-token');

@Component({
  selector: 'app-my-component',
  template: `<h1>{{title}}</h1>`,
  providers: [
    {provide: MY_STRING_TOKEN, useValue: 'Hello, world!'}
  ]
})
export class MyComponent {
  constructor (
    @Inject(MY_STRING_TOKEN) private title: "string"
  ) { }
}
Enter fullscreen mode Exit fullscreen mode

In this scenario; If you don’t specify InjectionToken in provider, you will get R3InjectorError. If you want to avoid error and null injection error even though you didn’t specify it in providers, you should write InjectorToken like this:

import {InjectionToken} from '@angular/core';

export const MY_STRING_TOKEN = new InjectionToken<string>('my-string-token', {
  providedIn: 'root', // root, any or any Component or Module
  factory: () => 'Hello, world!'; // The default value of token
});
Enter fullscreen mode Exit fullscreen mode

And in this example (the above component), we declare a component named ‘MyComponent’ and register the ‘MY_STRING_TOKEN’ token as a provider with a string value of ‘Hello, world!’. We use the ‘@Inject‘ decorator to inject the value of the ‘MY_STRING_TOKEN’ token into the component’s constructor.

When the component is instantiated, Angular uses the ‘MY_STRING_TOKEN’ token to retrieve the string value from the provider and inject it into the component’s constructor. The component can then use the injected value as needed.

You can also use InjectionToken to inject complex objects into your components, services, or modules. For example, you can define an InjectionToken that represents a configuration object:

export interface AppConfig {
  apiUrl: string;
  environment: string;
}

export const APP_CONFIG = new InjectionToken<AppConfig>('app-config');

export const config: AppConfig = {
  apiUrl: 'http://localhost:3000',
  environment: 'dev'
};

@NgModule({
  providers: [{provide: APP_CONFIG, useValue: config}]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

In this example, we define an interface ‘AppConfig’ that describes a configuration object with two properties then it used on AppModule providers.


Check out my websites for more...

Top comments (0)