angular: Child extends Parent dependecy not working

I have parent with injected http service:

import {Inject, Injectable, Component} from 'angular2/angular2';
import {Http} from 'angular2/http';

@Injectable()

export abstract class BaseResource {
    http:   Http;

    constructor(@Inject(Http) http: Http) {
        console.log("INITIALIZED", http); /// Output INITIALIZED but http is undefined

        this.http = http;
    }
}

And child what extends from Parent:

import {Injectable, Component} from 'angular2/angular2';
import {Headers} from 'angular2/http';
import {BaseResource} from './BaseResource';

@Component({
    providers[BaseResource]
})

@Injectable()

export class CarModel extends BaseResource  {
    postData(carId: number) {
        this.http.post(this.config.apiUrl); // http is undefined 
    }
}

Please note that child has no constructor as it suppose to use parent dependencies. But actually parent dependencies is not initalized for extends…

But it is ok if inject it directly without extends

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 9
  • Comments: 38 (17 by maintainers)

Most upvoted comments

@cajoy

let injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
this.http = injector.get(Http);

I came accross the same issue. The best solution is probably go with composition over inheritance.

Your before abstract class is now a “helper” which you will use to, let’s say, build the request and send the request.

Something like:

class RequestManager {
  constructor(http: Http) { }
  /* other methods */
}

class Service {
  constructor(requestManager: RequestManager) {}
  /* other methods */
}

Does this make sense?

@cajoy if you try to do this:

class Foo {
  constructor(public bar) {};
}

class ExtendsFoo extends Foo {
    constructor() {};
}

You will see that this is not a valid TS. On the other hand doing:

class ExtendsFoo extends Foo {
}

will transpile to:

var ExtendsFoo = (function (_super) {
    __extends(ExtendsFoo, _super);
    function ExtendsFoo() {
        _super.apply(this, arguments);
    }
    return ExtendsFoo;
})(Foo);

which basically calls super’s constructor with all arguments being undefined.

I hope that you can see from the above that you need to re-define and re-inject constructor arguments in a child class.

Let’s assume I have following class where:

import {Http} from 'angular2/http';
import {Config} from '../../Config';

export abstract class BaseResource {
    config: Config;
    http:   Http;

    constructor() {
        this.http = new Http();
        this.config = new Config();
    }
}

Config is base TS class and is injected without any issues and I can use it’s methods and properties. While Http is angular DI injection class… So I can not use this component without proper injection.

So the issue I see is Angular2/Http is not self-sustained component. So I can not use it as standalone.

It looks like Angular2 components are coupled to each other.

Is there any other way how I can inject Http in parent class? without touching Child?

Yes but in this case it makes no sense of e tended class as I need to redefine constructor parameters . It should be picked automatically and works fine for native TS but not works for DI

Is this is issue with DI or TS?

On Nov 6, 2015, at 4:39 AM, Pawel Kozlowski notifications@github.com wrote:

@cajoy if you try to do this:

class Foo { constructor(public bar) {}; }

class ExtendsFoo extends Foo { constructor() {}; } You will see that this is not a valid TS. On the other hand doing:

class ExtendsFoo extends Foo { } will transpile to:

var ExtendsFoo = (function (_super) { __extends(ExtendsFoo, _super); function ExtendsFoo() { _super.apply(this, arguments); } return ExtendsFoo; })(Foo); which basically calls super’s constructor with all arguments being undefined.

I hope that you can see from the above that you need to re-define and re-inject constructor arguments in a child class.

— Reply to this email directly or view it on GitHub.

It did resolved all issues!..

He he - I don’t think so 😃 Now you’ve got just a fancy way of doing new Http() with all the benefits of DI gone - but you have been warned 😃

It is not about angular or DI - it is about presence of a constructor with arguments. If you extend a class that has a constructor with arguments you need to do something about it - that is - call super with appropriate arguments. This is a requirement in any programming language I know of: with our without angular / di.

You seem to expect that ng’s DI system would violate this basic principle by going over class hierarchy and magically invoke child constructors, which I don’t think is a reasonable expectations.

It looks like Angular2 components are coupled to each other.

Once again, this has nothing to do with Angular. If one class extends another they are “coupled”.

@woppa684

import {Http} from 'angular2/http';
import {Config} from '../../Config';
import { Injector } from 'angular2/angular2';

export abstract class BaseResource {
    config: Config;
    http:   Http;

    constructor() {

        var injector = Injector.resolveAndCreateChild([
            Http
        ]);

        this.http = injector.get(Http);
        this.config = new Config();
    }
}

Gives me exception:

ORIGINAL EXCEPTION: No provider for ConnectionBackend! (Http -> ConnectionBackend)

Yes but in this case I need to inject http also what makes no sense…

Anyway parent constructor calls successfully but without injection

On Nov 5, 2015, at 10:26 PM, Torgeir Helgevold notifications@github.com wrote:

I think in TypeScript you have to add super() in a child constructor

export class CarModel extends BaseResource{ constructor(){ super(); }

postData(carId: number) { this.http.post(this.config.apiUrl); // http is undefined } } — Reply to this email directly or view it on GitHub.