7

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
    ); 
  }
}
0

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

7 Comments

It looks like there is missing something in the abstract class. this.anyOtherService` is not set yet, when you want to push something into it inside the constructor.
yes, you should define entityService as BaseComponent property
This is not fully the desired behaviour. FirstService should be injected as entityService and anyOtherService should only be an instance of anyOtherService.
Also I've got that error message: Types have separate declarations of a private property 'inject'.
removed private in child component and set as protected on base
|
1

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 );
  }
}

3 Comments

What do you mean by "export it from appmodule"? Should I add this to my app.module.ts?
@MichaelCzechowski - it like export let AppInjector: Injector; its can be your base module also where your base component resides , its not necessary to be at appmodule level , you can create in you module related to basecomponent and use
Careful: On the client side this works, but using a "global injector" approach like this with server-side-rendering (SSR) can cause serious problems like seemingly random mismatched user session/cookie data, because Angular sets up a fresh injector for each page load. Assigning AppInjector will happen for each request, and since all your requests run in the same runtime, if you pause one request for an async operation and another one comes in and executes, when you continue on the first request you will have the wrong request state within the injector held by AppInjector.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.