5

I'm writing a base class which contains the httpClient. It is used to make REST api calls. The httpClient variable is set correctly if defined in constructor, but not in private variable.

Here's my sample code:

@Injectable()
export class MyBaseClass implements {
  private httpClient = HttpClient

  constructor(
    private httpClient2: HttpClient
  ) {
    console.log("httpClient2", httpClient2)
    console.log("httpClient2.get", httpClient2.get)
  }
  callApi() {
    console.log("httpClient", this.httpClient)
    console.log("httpClient.get", this.httpClient.get)
  }
}

constructor output: enter image description here

callApi output: enter image description here

As you can see the two variables aren't the same and the get property of httpClient is undefined.

I would use the variable in the constructor throughout my class, but I what I want is to extend this class and having the variable in the constructor isn't convenient.

Any help/suggestions would be greatly appreciated.

Thanks,

Will

4
  • Can you make your base class in such a way that the derived classes don't need a specific constructor? Commented Mar 15, 2018 at 22:34
  • If you mean the subclass, then no. I have to run "super()" as my first statement in the constructor subclass. Commented Mar 15, 2018 at 22:35
  • Do you absolutely need a constructor in the derived class? Commented Mar 15, 2018 at 22:36
  • Not a bad idea, but I think I do need them. Commented Mar 15, 2018 at 23:29

2 Answers 2

12

There is another option if you really don't want to inject the services in your base class' constructor.

1. Declare a global variable containing a ref to the injector and assign it in your module (or somewhere else, before your base class'constructor is called)

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

export let InjectorInstance: Injector;

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

2 Then you can use it like this in your base class

import {InjectorInstance} from '../app.module';

export class MyBaseClass  
{
    private httpClient : HttpClient:

    constructor()
    {
        this.httpClient = InjectorInstance.get<HttpClient>(HttpClient);
    }

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

1 Comment

Interesting idea, I'll check it out. If works, I will probably make this my answer...thanks.
3

The property httpClient on your class is simply being set to the HttpClient class constructor. If you need an instance of that class, you need to let Angular provide it to you via dependency injection like your httpClient2 property (i.e. as a parameter to your constructor).

As a note, adding the private accessor to the parameter on the constructor is syntactic sugar that is doing the following:

class MyBaseClass {
    private httpClient2: HttpClient;

    constructor(httpClient2: HttpClient) {
        this.httpClient2 = httpClient2;
    }
}

13 Comments

I really want to avoid injecting it in the constructor.
Why?... That is how you do things properly in Angular
Without using dependency injection, you will make it difficult to properly test things, especially when you need to start mocking things like network calls
When I extend MyBaseClass, in the subclass I want to be able to call super(). Is it possible?
Yes that is what you would do
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.