Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection in abstract class with TypeScript and Angular 5

I've got the BaseComponent which got some dependencies injected. The first dependency EntityService is correct and necessary.

ButAnyOtherService is only used inside the abstract BaseComponent. Instead of injecting it inside the ChildComponent, where it is not used, I'd like to inject it only inside BaseComonent.

Why do I have to push it through the ChildComponent towards the BaseComponent? The best solution would be to encapsulate it inside the BaseComponent.

base.component.ts

export abstract class BaseComponent {
  constructor(
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) {
  }
}

child.component.ts

@Component()
export class ChildComponent extends BaseComponent {

  constructor(
    private firstService: FirstService,
    private secondService: SecondService,
    protected anyOtherService: AnyOtherService // @todo remove this
  ) {
    super(
      firstService,
      anyOtherService // @todo remove this
    ); 
  }
}
like image 892
Michael Czechowski Avatar asked Oct 16 '22 21:10

Michael Czechowski


2 Answers

So you can pass Injector to base component constructor(UPDATE):

export abstract class BaseComponent {
  protected anyOtherService: AnyOtherService;

  constructor(
    inject: Injector
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) { 
     this.anyOtherService= inject.get(AnyOtherService);
  }
}


@Component()
  export class ChildComponent extends BaseComponent {

  constructor(
    inject: Injector,
    private firstService: FirstService,
    private secondService: SecondService       
  ) {
    super(
     inject,
     firstService
    );       
  }
}

The idea is to inject Injector and some providers in child component and pass it to parent base component without passing all base class dependencies. With passing injector, child classes(components) doesn't need to inject all dependencies of parent(base) class and pass throw super(dep1, dep2..., baseDep1...).

Could you please explain in your answer, why it has to be like you've said with private inside child and protected inside parent?

I think the injector shouldn't be the property of child/base class. If will be, the error throws as you comment below. The error is about, Base and Child class can't have the same property in their class. That's why we need to omit private/protected or any access modifier to injector in constructor, also because Injector is only needed in constructor to manually inject what we need in some specific cases as this.

like image 105
Yerkon Avatar answered Oct 20 '22 15:10

Yerkon


you can try like this , make use of injector , export it from appmodule and use it in you base class

import {Injector} from '@angular/core';

//exporting injector 
export let AppInjector: Injector;

export class AppModule {
  constructor(private injector: Injector) {
    AppInjector = this.injector;
  }
}

and then base.component.ts

export abstract class BaseComponent {
  private anyOtherService : AnyOtherService ;
  constructor(
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) {
    this.anyOtherService = AppInjector.get(AnyOtherService );
  }
}
like image 41
Pranay Rana Avatar answered Oct 20 '22 15:10

Pranay Rana