2015-10-08 8 views
12

Wenn ich es6/7 (Babel - Stufe 1) anstelle von TypeScript verwende, wie werden Dienste und speziell Http, injiziert?Wie Angular2 HTTP-Dienst in es6/7 Klasse injizieren?

Hier sind meine Komponente JS:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2'; 
import {Http} from 'angular2/http'; 

@Component({ 
    selector: 'login' 
}) 
@View({ 
    templateUrl: './components/login/login.html', 
    styleUrls: ['components/login/login.css'], 
    directives: [CORE_DIRECTIVES], 
    encapsulation: ViewEncapsulation.Emulated 
}) 
export class Login { 
    constructor(@Inject(Http) http) { 
    console.log('http', http); 
    } 

    authenticate(username, password) { 
    // this.http.get('/login'); 
    } 
} 

ich versucht habe:

export class Login { 
    constructor(@Inject(Http) http) { 
    console.log('http', http); 
    } 
} 
/********************/ 
@Inject(Http) 
export class Login { 
    constructor(http) { 
    console.log('http', http); 
    } 
} 
/********************/ 
export class Login { 
    constructor(Http: http) { 
    console.log('http', http); 
    } 
} 
/********************/ 
export class Login { 
    constructor(http = Http) { 
    console.log('http', http); 
    } 
} 
/********************/ 
export class Login { 
    constructor(Http) { 
    this.http = new Http() 
    console.log('http', this.http); 
    } 
} 
/********************/ 
export class Login { 
    constructor(http = new Http()) { 
    console.log('http', http); 
    } 
} 

Alle aber die erste compiliert. Andere geben mir Zugriff auf die Http-Klasse oder eine http-Instanz. Aber keiner funktioniert.

Ich habe versucht, die Diskussion von Eric Martinez in seinem Kommentar zu folgen. Login.js jetzt:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2'; 
import {HTTP_BINDINGS, Http, BaseRequestOptions, RequestOptions, RequestMethods} from 'angular2/http'; 

@Component({ 
    selector: 'login' 
}) 
@View({ 
    templateUrl: './components/login/login.html', 
    styleUrls: ['components/login/login.css'], 
    directives: [CORE_DIRECTIVES], 
    encapsulation: ViewEncapsulation.Emulated, 
    bindings: [Http] 
}) 
export class Login { 

    constructor(http) { 
    this.http = http; 
    console.log('http', http); 
    } 

    authenticate(usernameEl, passwordEl) { 
    var username = usernameEl.value; 
    var password = passwordEl.value; 
    console.log('username', username, password); 

    // this.http.get('/login'); 
    } 
} 

Login.parameters = [Http]; 

Es kompiliert nun aber erzeugt den folgenden Fehler:

Uncaught (in promise) NoBindingError {message: "No provider for Http! (Login -> Http)", stack: "Error: DI Exception↵ at NoBindingError.BaseExce…or._new (http://localhost:3000/bundle.js:7319:22)", keys: Array[2], injectors: Array[2]}constructResolvingMessage: (keys)arguments: (...)caller: (...)length: 1name: ""prototype: Object__proto__:()context: (...)injectors: Array[2]0: Injector1: Injectorlength: 2__proto__: Array[0]keys: Array[2]message: "No provider for Http! (Login -> Http)"stack: "Error: DI Exception↵ at NoBindingError.BaseException [as constructor] (http://localhost:3000/bundle.js:8400:24)↵ at NoBindingError.AbstractBindingError [as constructor] (http://localhost:3000/bundle.js:9066:17)↵ at new NoBindingError (http://localhost:3000/bundle.js:9102:17)↵ at Injector._throwOrNull (http://localhost:3000/bundle.js:7469:20)↵ at Injector._getByKeyDefault (http://localhost:3000/bundle.js:7516:22)↵
at Injector._getByKey (http://localhost:3000/bundle.js:7461:26)↵ at Injector._getByDependency (http://localhost:3000/bundle.js:7447:26)↵
at Injector._instantiate (http://localhost:3000/bundle.js:7339:37)↵
at Injector._instantiateBinding (http://localhost:3000/bundle.js:7330:26)↵ at Injector._new (http://localhost:3000/bundle.js:7319:22)"proto: __

+0

Siehe [diese Ausgabe] (https://github.com/angular/angular/issues/4334) und [@brandonroberts Kommentare] (https://github.com/angular/angular/issues/4334#issuecomment- 142676405) –

+0

@EricMartinez Danke für die Referenz. Ich änderte es, um meinem Verständnis der Diskussion zu entsprechen. Leider erhalte ich einen Fehler. –

+0

Ändern Sie diese Zeile 'bindings: [Http]' in 'bindings: [HTTP_BINDINGS]' und setzen Sie sie in '@ Component' Annotation und versuchen Sie es erneut. –

Antwort

13

Da Sie @Decorators in Babel aktiviert

... Ich werde die Feinabstimmung diese Antwort mit Ihrem spezifischen Setup arbeiten .

1. Sie verpassen HTTP_PROVIDERS

Die HTTP_PROVIDERS Konstante enthält eine Reihe von Funktionen erforderlich, um HTTP-Anfragen/Antworten zu behandeln.

import {Http, HTTP_PROVIDERS} from 'angular2/http';  

@Component({ 
    selector: 'login', 
    providers: [ HTTP_PROVIDERS ] 
}) 

2. Sie müssen den DI (Dependency Injection) Syntax

erwähnt desugar Wie in @alexpods' answer.

Entfernen Sie die statische Typisierung

constructor(http) { 

@Inject DI implizit behandelt, sondern nur in Angular2 + Typoskript unterstützt. Da Sie Angular2 + ES6 verwenden, müssen Sie einen statischen Getter-Parameter an Ihre Klasse anhängen, um das ES6-spezifische Äquivalent bereitzustellen.

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

3. Sie müssen die Http-Instanz in Ihrer Klasse im Konstruktor

Dadurch dies binden, wird es in Ihrem authenticate() Verfahren zugänglich werden.

constructor(http) { 
    this.http = http; 
    console.log('http', this.http); 
} 

... und die vollständige Umsetzung:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2'; 
import {Http, HTTP_PROVIDERS} from 'angular2/http'; 

@Component({ 
    selector: 'login', 
    // required for Http 
    providers: [ HTTP_PROVIDERS ] 
}) 
@View({ 
    templateUrl: './components/login/login.html', 
    styleUrls: ['components/login/login.css'], 
    directives: [CORE_DIRECTIVES], 
    encapsulation: ViewEncapsulation.Emulated 
}) 
export class Login { 
    constructor(http) { 
    // bind http to your class during construction 
    // so it's available to authenticate() 
    this.http = http; 
    } 

    // Angular2 DI desugar'd 
    static get parameters() { 
    return [[Http]]; 
    } 

    authenticate(username, password) { 
    this.http.get('/login'); 
    } 
} 

Abgesehen: Ich weiß für eine Tatsache, das funktioniert, weil ich es für die <ng2-markdown> Komponente bin auf EvanPlaice.com.

9

Wie habe ich bereits beantwortet es here, Wenn Sie Code in ES7 schreiben, verwenden statische Getter für parameters Eigenschaft zur Angabe von Injektionen in constructor Ihrer Komponente. Zum Beispiel:

import { Http } from 'angular2/http'; 
// other imports ... 

// component decorators ... 
export class Login { 

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

    constructor(http) { 
    this.http = http; 
    console.log('http', http); 
    } 

    // other methods 
} 

Ich denke, es ist die prägnanteste Methode in diesem Moment.

Denken Sie daran, dass in diesem Moment kein Vorschlag zur Unterstützung von Parameter-Dekoratoren in ES7 vorliegt (z. B. see this issue for Babel).

+0

alexpds, danke für die Infos und Referenzen. Leider funktioniert Bootstrapping App aber nicht in der Komponente. Es löst einen NoBindingError aus. Ich habe auch versucht, [HTTP] und HTTP_BINDINGS zurückzugeben, sah aber immer noch einen NoBindingError. Ich habe bemerkt, dass in der SO-Antwort, auf die Sie verwiesen haben, der Plünderer Traceur enthalten hat. Ich versuche zu reproduzieren, was ich in einem anderen Kolben nur mit Babel sehe. Hinweis: Ich konnte es mithilfe von Eric Martinez 'Kommentar zur Arbeit bringen. –

+0

http://plnkr.co/edit/ZndMOk2VNmd5Es4qf4yk? P = Vorschau –

+0

@rob_hicks Hier http://plnkr.co/edit/P2EOeD53aJHt3poD9YU6?p=preview – alexpods

0

Methode von den offiziellen API Review funktioniert bei mir:

import {Http, HTTP_PROVIDERS} from 'angular2/http'; 
@Component({ 
    selector: 'http-app', 
    viewProviders: [HTTP_PROVIDERS], 
    templateUrl: 'people.html' 
}) 
class PeopleComponent { 
    constructor(http: Http) { 
    http.get('people.json') 
     .map(res => res.json()) 
     .subscribe(people => this.people = people); 
    } 
} 
+0

Welchen Transpiler benutzen Sie? Haben Sie ein Optionsflag gesetzt oder schließen Sie Polyfills ein? –

0

Mit babel-plugin-angular2-annotations können Sie Dienste mit Konstrukt injizieren oder Anmerkungen zum Parametertyp, genau wie TypeScript.

installieren babel Plugins:

npm install -D babel-plugin-angular2-annotations babel-plugin-transform-decorators-legacy babel-plugin-transform-class-properties babel-plugin-transform-flow-strip-types babel-preset-es2015 

.babelrc:

{ 
    "plugins": [ 
    "angular2-annotations", 
    "transform-decorators-legacy", 
    "transform-class-properties", 
    "transform-flow-strip-types" 
    ], 
    "presets": [ 
    "es2015" 
    ] 
} 

und voila!

Beachten Sie, dass die Typ-Signatur nur für einen Hinweis auf Abhängigkeitsinjektion und nicht für Typprüfung verwendet wird.

+0

Für jeden anderen schlug ich meinen Kopf gegen die Wand, weil ich meine Babel-Plugins in der falschen Reihenfolge aufgelistet hatte - stelle sicher, dass es in der gleichen Reihenfolge wie hier ist. (Anmerkungen zuerst) – Joao