2

I have class Layer:

import {AfterViewInit, ViewChild} from 'angular2/core';


export class Layer implements AfterViewInit {
  @ViewChild('element') element;

  public canvas: HTMLCanvasElement = null;
  public context: CanvasRenderingContext2D = null;

  ngAfterViewInit() {
    this.canvas = this.element.nativeElement;
    this.context = this.canvas.getContext('2d');
  }
}

which I will be extending with my component Lines:

import {Component} from 'angular2/core';

import {Layer} from './layer';
import {Game} from '../../providers/Game';


@Component({
  selector: 'lines-component',
  template: require('./template.html'),
  styles: [`
    canvas {
      z-index: 2;
    }
  `]
})
export class Lines extends Layer {
  constructor(public game: Game) {
    super();
  }
}

As you can see, I have to inject Game service to every component which will inherit from Layer. However, I would like to inject service to Layer class, so I can use it to create methods which depends on the service, and also it won't force me to inject service to the component on my own every single time.

Needless to say, injecting service to Layer as I would to any component is not working.

I am using angular 2.0.0-beta.0

Eggy
  • 4,052
  • 7
  • 23
  • 39

2 Answers2

2

Add the constructor to the base class Layer just like you did on the extending class, and send the dependency as a parameter in the super method:

export class Layer implements AfterViewInit {
    constructor(public game: Game) {
        console.log(game);
    }
}

export class Lines extends Layer {
  constructor(public game: Game) {
    super(game);
  }
}
Langley
  • 5,326
  • 2
  • 26
  • 42
  • 1
    Kind of sad that I have to pass dependency as parameter to `super()`, but at least it's working. – Eggy Jan 15 '16 at 16:42
0

I think that it's something not supported by Angular. You need to have a constructor at the level of the component to define what you want to inject...

Using your sample:

export class Layer {
  constructor(public game: Game) {
  }
}

@Component({
  (...)
})
export class Lines extends Layer {
  (...)
}

If you have a look at the transpiled file for the Lines class, you see that the game parameter is present in the Lines constructor function and the Game service isn't present in the second parameter (the list of providers for the component) of the __metadata function:

Lines = (function (_super) {
  __extends(Lines, _super);
  function Lines() { // <------------------
    _super.apply(this, arguments);
  }
  Lines = __decorate([
    core_1.Component({
      selector: 'lines-component',
      template: "\n    lines\n  ",
      styles: ["\n    canvas {\n      z-index: 2;\n    }\n  "]
    }), 
    __metadata('design:paramtypes', []) // <------------------
  ], Lines);
  return Lines;
})(app_layer_component_1.Layer);

whereas you have it when defining constructor(public game: Game) in the Lines class:

Lines = (function (_super) {
  __extends(Lines, _super);
  function Lines(game) { // <------------------
    this.game = game;
  }
  Lines = __decorate([
    core_1.Component({
      selector: 'lines-component',
      template: "\n    lines\n  ",
      styles: ["\n    canvas {\n      z-index: 2;\n    }\n  "]
    }), 
    __metadata('design:paramtypes', [app_game_service_1.Game]) // <------------------
  ], Lines);
  return Lines;
})(app_layer_component_1.Layer);

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • It is interesting, maybe injection is possible only when class have some decorator specified? – Eggy Jan 15 '16 at 16:57