Utilizing a simple helper array known as "registry" and a dedicated array provider, we can efficiently access all registered instances. See the example code snippet below:
export class Examples extends Array<ExampleService> {}
const examplesRegistry = [ExampleServiceA, ExampleServiceB];
export function buildExampleProviders() {
return [
...examplesRegistry,
{
provide: Examples,
useFactory: (...args) => new Examples(...args),
deps: examplesRegistry,
},
];
}
As illustrated, we can inject individual instances (like
protected exampleA: ExampleServiceA
) or all of them with
protected examples: Examples
)
Complete Example and Usage
/// example.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export abstract class ExampleService {
someProperty = Math.random();
abstract name: string;
}
@Injectable()
export class ExampleServiceA extends ExampleService {
override name = 'a';
}
@Injectable()
export class ExampleServiceB extends ExampleService {
override name = 'b';
}
/// examples.ts
export class Examples extends Array<ExampleService> {}
const examplesRegistry = [ExampleServiceA, ExampleServiceB];
export function buildExampleProviders() {
return [
...examplesRegistry,
{
provide: Examples,
useFactory: (...args) => new Examples(...args),
deps: examplesRegistry,
},
];
}
/// app.component.ts
import { Component } from '@angular/core';
import { ExampleServiceA } from './example.service';
import { buildExampleProviders, Examples } from './examples';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [buildExampleProviders()],
})
export class AppComponent {
constructor(
protected examples: Examples,
protected exampleA: ExampleServiceA
) {}
}
<!-- app.component.html -->
<pre>
<ng-container *ngFor="let ex of examples; let i = index">
examples[{{i}}]:
.name: {{ ex.name }}
.someProperty: {{ ex.someProperty }}
.constructor.name: {{ ex.constructor.name }}
</ng-container>
exampleA:
.name: {{ exampleA.name }}
.someProperty: {{ exampleA.someProperty }}
.constructor.name: {{ exampleA.constructor.name }}
</pre>
To explore this further, check out the example code on StackBlitz:
https://stackblitz.com/edit/angular-ivy-3kaagr?file=src/app/examples.ts