Dependency injection into abstract class typescript(Angular2) Dependency injection into abstract class typescript(Angular2) typescript typescript

Dependency injection into abstract class typescript(Angular2)


As of Angular 2 RC5 the DI becomes simpler. You don't need to decorate the stuff with @Injectable(). Instead, you just declare it for DI in one place - NgModule.

export class ErrorHandler {    test() {        console.log('ErrorHandler.test()');    }}export abstract class BaseApiComponent<T> {    // use protected property parameter in abstract class    // for accessibility from descendants.    constructor(protected errorHandler: ErrorHandler) {}    someMethod() {        this.errorHandler.test();    }}export class ApiComponentImpl<T> extends BaseApiComponent<T> {    // use @Inject decorator    constructor(@Inject(ErrorHandler) errorHandler: ErrorHandler) {        super(errorHandler);    }}

app.module.ts:

// class declarations@NgModule({    providers: [        ErrorHandler,        ApiComponentImpl    ]})export class AppModule{}// bootstrap the appplatformBrowserDynamic().bootstrapModule(AppModule);

You can employ OpaqueToken to improve modularity and remove type dependency:

export const errorHandlerToken = new OpaqueToken('ErrorHandler');

in the module:

    providers: [        // using OpaqueTokens you can change the provided value        // to anything without changing consumer code         {provide: errorHandlerToken, useClass: ErrorHandler},

constructor:

    constructor(@Inject(errorHandlerToken) errorHandler: ErrorHandler) {


Angular DI only supports constructor injection, which means you need a constructor.

You also can't inject into an abstract class directly because an abstract class is not supposed to be instantiatable.

Therefore it has to be like:

export abstract class BaseApiComponent<T> {    constructor(errorHandler: ErrorHandler) {}    someMethod() {     this.errorHandler.test();    }}export class ApiComponentImpl<T> {    constructor(errorHandler: ErrorHandler) {      super(errorHandler);    }}


I'm not an angular developer, but looking at the examples the @Inject decorator is always used as a parameter decorator and not as a property decorator.

As the two decorator types are different, that might cause the problem but I'm not sure.
Try:

export abstract class BaseApiComponent<T> {    private errorHandler: ErrorHandler;    protected constructor(@Inject(ErrorHandler) handler) {        this.errorHandler = handler;    }    public error() {        this.errorHandler.test();    }}

Also I'm not sure when you're actually using this.errorHandler.test(); as it can't just sit there in the class, I moved it into the error method.


edit

Right. You'll need to inject in the extending class and then pass the instance to the parent:

export abstract class BaseApiComponent<T> {    protected errorHandler: ErrorHandler;    protected constructor(handler: ErrorHandler) {        this.errorHandler = handler;    }}export class Restaurants extends BaseApiComponent<any> {    constructor(@Inject(ErrorHandler) handler) {        super(handler);    }}