Angular 2: How Should We Be Handling Dependency Injection with ES6/ES7?

时光怂恿深爱的人放手 提交于 2019-12-12 19:22:51

问题


I have been working on a custom component within Angular 2 as I attempt to learn the ropes and make the switch while staying with ES6/ES7 due to job constraints. Say I have a component defined such as this:

// Import Inject, Component and View constructor (for metadata)
import {Inject, Injectable} from 'angular2/core';
import {Component, View} from 'angular2/core';
// Import NgClass directive
import {NgClass} from 'angular2/common';

import { InjectMetadata } from 'angular2/core';

// # Accordion Component

@Component({
  selector: 'accordion, [accordion]',

  // Modify the `host` element with a css class designator
  host: {
    'class': 'panel-group'
  }
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion.html'
})

// Create and export `Component` class
export class Accordion {

  constructor() {

    this.groups = [];
  }

  // Function to register groups
  addGroup(group) {
    this.groups.push(group);
  }

  closeOthers(openGroup) {
    this.groups.forEach((group) => {
      if(group !== openGroup) {
        group.isOpen = false;
      }
    });
  }

  removeGroup(group) {
    let index = this.groups.indexOf(group);

    if(index !== -1) {
      this.groups.splice(index, 1);
    }
  }
}

I need to pass this into another component called AccordionGroup but when I follow the answers in this Stack Overflow Thread and try to inject like I do with the constructor:

// # AccordionGroup Component

// Annotate AccordionGroup class with `Component`
@Component({
  selector: 'accordion-group, [accordion-group]',
  inputs: ['heading', 'isOpen'],

  // Let Angular know about `Accordion`
  providers: [Accordion]
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion-group.html',

  // Specify which directives our `Component` will utilize with
  // the `directive` property of the `View` annotation
  directives: [NgClass]
})

// Create and export `Component` class
export class AccordionGroup {

  constructor(accordion) {

    this.isOpen = false;

    this.accordion = accordion;

    this.accordion.addGroup(this);
  }

  // Angular 2 DI desugar'd
  // Reference: https://stackoverflow.com/questions/33026015/how-to-inject-angular2-http-service-into-es6-7-class
  static get parameters() {
    return [[Accordion]];
  }

  toggleOpen(event) {
    event.preventDefault();
    this.isOpen = !this.isOpen;
    this.accordion.closeOthers(this);
  }

  onDestroy() {
    this.accordion.removeGroup(this);
  }
}

using

static get parameters() {
  return [[Accordion]];
}

renders my component after making the correction noted in the first comment.

Using any of the following renders the component:

AccordionGroup.parameters = [[Accordion]];

or

AccordionGroup.parameters = [new Inject(Accordion)];

or even

// Use reflect metadata as an attempt to inject appropriate
// dependency
@Reflect.metadata('parameters', [[new InjectMetadata(Accordion)]])

but the question remain, which of these is the appropriate method to use until such a time when we can use parameter decorators with ES7.

As an aside, a lot of the code came from this particular tutorial which demonstrates all of the Angular 2 stuff with TypeScript, so I simply adapted it to my es6/es7 environment with Webpack | Migrating Directives to Angular 2


回答1:


You need to add the @Inject() decorator on your constructor parameter. As this is not supported by the ES7 spec (only class, property and methods decorators are allowed in the current spec AFAIK), you need to have some kind of plugin for your transpiler.

If you are using Babel to transpile, you can use the babel-plugin-angular2-annotations plugin to allow this and correctly transpile the code.

import {Inject} from 'angular2/core';

export class AccordionGroup {
  constructor(@Inject(Accordion) accordion) {
    // ...
  }
}



回答2:


In addition to what Eric said in comment, perhaps you missed the @Inject decorator within the AccordionGroup constructor

import {Inject} from 'angular2/core';

export class AccordionGroup {
  constructor(@Inject(Accordion) accordion) {
    (...)
  }
}

Hope it helps you, Thierry



来源:https://stackoverflow.com/questions/35089037/angular-2-how-should-we-be-handling-dependency-injection-with-es6-es7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!