I have a set of angular2 components that should all get some service injected. My first thought was that it would be best to create a super class and inject the service there. Any of my components would then extend that superclass but this approach does not work.
Simplified example:
export class AbstractComponent {
constructor(private myservice: MyService) {
// Inject the service I need for all components
}
}
export MyComponent extends AbstractComponent {
constructor(private anotherService: AnotherService) {
super(); // This gives an error as super constructor needs an argument
}
}
I could solve this by injecting MyService
within each and every component and use that argument for the super()
call but that's definetly some kind of absurd.
How to organize my components correctly so that they inherit a service from the super class?
In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.
Dependency injection enables you to turn regular Java classes into managed objects and to inject them into any other managed object. Using dependency injection, your code can declare dependencies on any managed object.
In object-oriented programming (OOP) software design, dependency injection (DI) is the process of supplying a resource that a given piece of code requires. The required resource, which is often a component of the application itself, is called a dependency.
I could solve this by injecting MyService within each and every component and use that argument for the super() call but that's definetly some kind of absurd.
It's not absurd. This is how constructors and constructor injection works.
Every injectable class has to declare the dependencies as constructor parameters and if the superclass also has dependencies these need to be listed in the subclass' constructor as well and passed along to the superclass with the super(dep1, dep2)
call.
Passing around an injector and acquiring dependencies imperatively has serious disadvantages.
It hides dependencies which makes code harder to read.
It violates expectations of one familiar with how Angular2 DI works.
It breaks offline compilation that generates static code to replace declarative and imperative DI to improve performance and reduce code size.
Updated solution, prevents multiple instances of myService being generated by using the global injector.
import {Injector} from '@angular/core';
import {MyServiceA} from './myServiceA';
import {MyServiceB} from './myServiceB';
import {MyServiceC} from './myServiceC';
export class AbstractComponent {
protected myServiceA:MyServiceA;
protected myServiceB:MyServiceB;
protected myServiceC:MyServiceC;
constructor(injector: Injector) {
this.settingsServiceA = injector.get(MyServiceA);
this.settingsServiceB = injector.get(MyServiceB);
this.settingsServiceB = injector.get(MyServiceC);
}
}
export MyComponent extends AbstractComponent {
constructor(
private anotherService: AnotherService,
injector: Injector
) {
super(injector);
this.myServiceA.JustCallSomeMethod();
this.myServiceB.JustCallAnotherMethod();
this.myServiceC.JustOneMoreMethod();
}
}
This will ensure that MyService can be used within any class that extends AbstractComponent without the need to inject MyService in every derived class.
There are some cons to this solution (see Ccomment from @Günter Zöchbauer below my original question):
For a very well written explanation of dependency injection in Angular2 see this blog post which helped me greatly to solve the problem: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
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