Supposons que je dispose d'une directive de composant angulaire à deux composants, dans laquelle je souhaite que la dépendance injectée utilisée par le composant soit déterminée par un @Input ().
Je veux écrire quelque chose comme <trendy-directive use="'serviceA'">
et que cette instance de TrendyDirective utilise serviceA, ou utilise serviceB si c'est ce que je spécifie. (ceci est une version simplifiée à l'extrême de ce que j'essaie de faire)
(Si vous pensez que c'est une idée terrible pour commencer, je suis ouvert à ce retour, mais expliquez pourquoi.)
Voici un exemple de réalisation de ce à quoi je pense. Dans cet exemple, imaginons que ServiceA et ServiceB sont des injectables qui implémentent tous les deux iService en ayant un 'superCoolFunction'.
@Component({
selector: 'trendy-directive',
...
})
export class TrendyDirective implements OnInit {
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB){}
private service: iService;
@Input() use: string;
ngOnInit() {
switch (this.use){
case: 'serviceA': this.service = this.serviceA; break;
case: 'serviceB': this.service = this.serviceB; break;
default: throw "There's no such thing as a " + this.use + '!';
}
this.service.superCoolFunction();
}
}
Je pense que cela fonctionnerait techniquement, mais il doit y avoir une meilleure façon de faire une injection dynamique de dépendance.
Il est
// can be a service also for overriding and testing
export const trendyServiceMap = {
serviceA: ServiceA,
serviceB: ServiceB
}
constructor(private injector: Injector) {}
...
ngOnInit() {
if (trendyServiceMap.hasOwnProperty(this.use)) {
this.service = this.injector.get<any>(trendyServiceMap[this.use]);
} else {
throw new Error(`There's no such thing as '${this.use}'`);
}
}
En général, la même approche est décrite dans la documentation Angular2: InjectorComponent
@Component({
providers: [Car, Engine, Tires, heroServiceProvider, Logger]
})
export class InjectorComponent {
car: Car = this.injector.get(Car);
heroService: HeroService = this.injector.get(HeroService);
hero: Hero = this.heroService.getHeroes()[0];
constructor(private injector: Injector) { }
}
Vous devez injecter Injector
dans le constructeur et répertorier tous les services dans la propriété providers
de l'annotation @Component
. Ensuite, vous pouvez injector.get(type)
, où type
sera résolu à partir de votre @Input
. Conformément à la documentation, Service
n’est réellement injecté que lorsque vous le demandez (.get()
).
Il existe un service nommé Inject in @ angular/core module. Avec @Inject, vous pouvez réaliser un autre mode d'injection. Mais cela ne peut être fait que dans le constructeur.
Vous devrez donc placer les entrées de composant dans le tableau d'entrées de votre décorateur @component (n'utilisez pas de décorateur @Input dans la classe), puis injecter cette variable d'entrée dans le constructeur.