Multi-Providers in Angular
Multi-Providers in Angular allow you to provide multiple values for a single token. This is particularly useful for creating extensible features such as logging, middleware, or plugins where multiple implementations need to be aggregated.
Understanding Multi-Providers
To use multi-providers, you define a token and specify that it should use multiple providers by setting the multi
property to true
:
// logging.service.ts
import { InjectionToken } from '@angular/core';
export const LOGGING_TOKEN = new InjectionToken<string[]>('LoggingToken');
Providing Multiple Values
To provide multiple values for a single token, use the multi: true
option in the provider configuration:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { LOGGING_TOKEN } from './logging.service';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [
{ provide: LOGGING_TOKEN, useValue: 'LogEntry1', multi: true },
{ provide: LOGGING_TOKEN, useValue: 'LogEntry2', multi: true },
{ provide: LOGGING_TOKEN, useValue: 'LogEntry3', multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
Injecting Multiple Values
When you inject the token into a component or service, Angular will provide an array containing all the values:
// my.component.ts
import { Component, Inject } from '@angular/core';
import { LOGGING_TOKEN } from './logging.service';
@Component({
selector: 'app-my-component',
template: '{{ log }}',
})
export class MyComponent {
constructor(@Inject(LOGGING_TOKEN) public logs: string[]) { }
}
In this example, the logs
array in the component will contain ['LogEntry1', 'LogEntry2', 'LogEntry3']
.
Using Multi-Providers with Classes
Multi-providers can also be used with class providers, allowing multiple implementations of an interface to be injected:
// notification.service.ts
export interface Notification {
send(message: string): void;
}
export class EmailNotification implements Notification {
send(message: string): void {
console.log('Email: ' + message);
}
}
export class SMSNotification implements Notification {
send(message: string): void {
console.log('SMS: ' + message);
}
}
export const NOTIFICATION_TOKEN = new InjectionToken<Notification[]>('NotificationToken');
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { NOTIFICATION_TOKEN, EmailNotification, SMSNotification } from './notification.service';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [
{ provide: NOTIFICATION_TOKEN, useClass: EmailNotification, multi: true },
{ provide: NOTIFICATION_TOKEN, useClass: SMSNotification, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
// my.component.ts
import { Component, Inject } from '@angular/core';
import { NOTIFICATION_TOKEN, Notification } from '../notification.service';
@Component({
selector: 'app-my-component',
template: '',
})
export class MyComponent {
constructor(@Inject(NOTIFICATION_TOKEN) private notifications: Notification[]) { }
sendNotifications() {
this.notifications.forEach(notification => notification.send('Hello!'));
}
}
In this example, both EmailNotification
and SMSNotification
will be injected and used to send notifications.
Key Points
- Multi-Providers allow multiple values for a single token.
- They are useful for extensible patterns like logging, middleware, or plugins.
- Use the
multi: true
option in the provider configuration to enable multi-providers. - Injected values are available as an array, which can contain strings, objects, or class instances.
Conclusion
Multi-Providers in Angular provide a powerful way to manage multiple values or implementations for a single token. By using multi-providers, you can create flexible and extensible features in your Angular applications. Understanding and leveraging multi-providers will help you build more modular and maintainable code.