11736

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

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

Answer1:

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) {
    // ...
  }
}

    

Answer2:

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

Recommend

  • How to access components of jFrame from other class?
  • How to run code sequentially with parse, in Android?
  • Intellisense keeps showing errors while build is successful Visual Studio 2015
  • Level-order tree traversal
  • Function calling incorrect values
  • Why is my req.body always empty on POST?
  • Deploying pre-encrypted configuration files to a production environment
  • Regex for incomplete lines within known start and end strings
  • How to upload files in php using html
  • Instanciate service on startup in Angular2
  • Linq Full Outer Join on Two Objects
  • get passwords from chrome
  • Get the App path without the app name at the end of the app
  • Reassigning an array frees the memory used by it?
  • jersey/tomcat Description The origin server did not find a current representation for the target res
  • Accessing Rows In A LINQ Result Without A Foreach Loop?
  • iText RadioGroup/RadioButtons across multiple PdfPCells
  • NSIS decompiler
  • Magento get URL before current
  • How to 'create temp table as select' in Slick?
  • How load cv2.KeyPoint and Descriptors correctly on OpenCV 3 with Python 3?
  • How do I include a SWC in an AS2 Flash project?
  • Zurb Foundation _global.scss meta styles for js?
  • Installing iPhone App to iPhone
  • Paperclip, set path outside of rails root folder
  • Change JButton Shape while respecting Look And Feel
  • Updating server-side rendering client-side
  • Comma separated Values
  • How to get icons for entities from eclipse?
  • Proper way to use connect-multiparty with express.js?
  • Load html files in TinyMce
  • Error creating VM instance in Google Compute Engine
  • Hits per day in Google Big Query
  • how does django model after text[] in postgresql [duplicate]
  • Cant find why the layout is getting smaller
  • JaxB to read class hierarchy
  • Observable and ngFor in Angular 2
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?