Is it a good practice to inject 'service' dependencies in @Input
properties? The service in this context is not a singleton instance managed at the root level but multiple instances of different implementations of the interface.
Consider the following example: In an Angular library, the ShapeComponent has a dependency on ShapeService (interface).
Component
@Component({
selector: 'ex-shape',
templateUrl: '..',
})
export class ShapeComponent {
constructor(shapeServiceCtor: ShapeService)
@Input shapeServiceInput: ShapeService;
}
A simple way to resolve the dependency is to set the input property as shown in the following code.
<ex-shape [shapeServiceInput]="rectangleShapeService" />
<ex-shape [shapeServiceInput]="ellipseShapeService" />
<ex-shape [shapeServiceInput]="polygonShapeService" />
Does the above approach hold good in resolving dependencies in Components?
If the input property approach is used then the services/dependencies have to the propagated to the child components in the same fashion. The downside of this approach is that the parent component will have to accept all the dependencies as input properties.
Are there any recommended approaches to inject and scope dependencies at the library level?
You're not really using Angular's dependency injection at this point, which in your case I'm not sure is good or bad.
If the ShapeComponent has no way to know what instance of the service it's using, and any time you call it you need to pass an arbitrary instance, this should be ok.
If the parent of the ShapeComponent will always pass the same instance of the service, the parent could include it in its providers
array and then children ShapeComponents will use that same instance.
Angular's docs have some more detailed info on the DI Hierarchy https://angular.io/guide/hierarchical-dependency-injection
Your call to constructor(shapeServiceCtor: ShapeService)
will also lead to some confusion, as the component will have both the DI injected one, and another (or possibly the same) instance from the @Input
This could work in your case:
@Component({
selector: 'ex-shape',
templateUrl: '..',
})
export class ShapeComponent {
// change the type to any since any service will be comping as input
private shapeServiceCtor: any;
constructor(
private injector: Injector // injector to inject incoming services
) {}
// type as any
@Input shapeServiceInput: any;
ngOnInit() {
// this will inject the service
this.shapeServiceCtor = this.injector(shapeServiceInput);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With