Injection tokens are a feature of Angular that allows the injection of values that don't have a runtime representation. What we mean by this, is that you can't inject something like an interface as it only exists as a TypeScript construct, not JavaScript. Injection tokens provide a simple mechanism to link a token, to a value, and have that value injected into a component.
To get started, let's declare an injection token:
import { InjectionToken } from '@angular/core'
export const MY_TOKEN = new InjectionToken<string>('MyToken');
The constructor accepts a description, and an optional options
map which allows you to customise the behaviour of the token. Given that token, we can define a provider:
@NgModue({
providers: [
{ provide: MY_TOKEN, useValue: 'Hello world' }
]
})
export class AppModule { }
Which, in turn allows you to inject the value into your component:
@Component({
selector: 'my-component',
template: '<h1>{{ value }}</h1>'
})
export class MyComponent {
constructor(@Inject(MY_TOKEN) public value: string) { }
}
Injection tokens become a secret to Angular extensibility. Let's look at an extended example, let's say a dynamic menu system:
export interface MenuItem {
label: string;
route: any[];
}
We could define an injection token based on our interface:
export const SETTINGS_MENU = new InjectionToken<MenuItem>('Settings');
Imagine if you will, in many modules, we could define menu items:
const moduleOneMenu: MenuItem = {
label: 'Module one',
route: ['/module-one']
};
@NgModule({
providers: [
{ provide: SETTINGS_MENU, useValue: moduleOneMenu, multi: true }
]
})
export class ModuleOne { }
And perhaps also:
const moduleTwoMenu: MenuItem = {
label: 'Module two',
route: ['/module-two']
};
@NgModule({
providers: [
{ provide: SETTINGS_MENU, useValue: moduleTwoMenu, multi: true }
]
})
export class ModuleTwo { }
Using the multi
property, this allows us to inject many items into our component:
@Component({
selector: 'my-menu',
template: `
<ul>
<li *ngFor="let item of items">
<a [routeLink]="item.route">{{ item.label }}</a>
</li>
</ul>`
})
export class MenuComponent {
constructor(@Inject(SETTINGS_MENU) public items: MenuItem[]) { }
}
Injection tokens are a powerful feature of Angular that allows us to compose applications in variety of extensible ways.