Как внедрить Angular2 Http-сервис в класс es6/7?
Если я использую es6/7 (babel - stage 1) вместо TypeScript, как вставляются услуги и, в частности, Http?
Здесь мой компонент 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');
}
}
Я пробовал:
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);
}
}
Все, кроме первого компиляции. Другие дают мне доступ к классу Http или к экземпляру http. Но никто не работает.
Я попытался после обсуждения, упомянутого Эриком Мартинесом в его комментарии. Login.js:
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];
Теперь он компилируется, но генерирует следующую ошибку:
Неподготовлено (в обещании) NoBindingError {сообщение: "Нет провайдера для Http! (Login → Http)", стек: "Ошибка: исключение DI" в NoBindingError.BaseExce... or._new (http://localhost:3000/bundle.js:7319:22) ", keys: Array [2], инжекторы: 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] сообщение: "Нет провайдера для Http! (Login → Http)" stack:" Ошибка: DI Exception↵ at NoBindingError.BaseException [как конструктор] (http://localhost:3000/bundle.js:8400:24) ↵ при NoBindingError.AbstractBindingError [как конструктор] (http://localhost:3000/bundle.js:9066:17) ↵ при новом NoBindingError (http://localhost:3000/bundle.js:9102:17) ↵ на Injector._throwOrNull (http://localhost:3000/bundle.js:7469:20) ↵ при Injector._getByKeyDefault (http://localhost:3000/bundle.js:7516:22) ↵
в Injector._getByKey (http://localhost:3000/bundle.js:7461:26) ↵ при Injector._getByDependency (http://localhost:3000/bundle.js:7447:26) ↵
в Injector._instantiate (http://localhost:3000/bundle.js:7339:37) ↵
в Injector._instantiateBinding (http://localhost:3000/bundle.js:7330:26) ↵ на Injector._new (http://localhost:3000/bundle.js:7319:22)" Прото: __
Ответы
Ответ 1
Поскольку у вас есть @Decorators
включено в Babel
... Я отрегулирую этот ответ, чтобы работать с вашей конкретной настройкой.
1. Вам не хватает HTTP_PROVIDERS
Константа HTTP_PROVIDERS включает в себя ряд функций, необходимых для обработки HTTP-запросов/ответов.
import {Http, HTTP_PROVIDERS} from 'angular2/http';
@Component({
selector: 'login',
providers: [ HTTP_PROVIDERS ]
})
2. Вам нужно отменить синтаксис DI (зависимость)
Как указано в ответе @alexpods.
Удаление статического ввода
constructor(http) {
@Inject обрабатывает DI неявно, но поддерживается только в Angular2 + Typescript. Поскольку вы используете Angular2 + ES6, вам необходимо прикрепить статический параметр getter к вашему классу, чтобы обеспечить эквивалент ES6.
static get parameters() {
return [[Http]];
}
3. Вам нужно связать экземпляр Http с вашим классом в конструкторе
Посредством этого он станет доступен в вашем методе authenticate()
.
constructor(http) {
this.http = http;
console.log('http', this.http);
}
... и полная реализация:
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 available to authenticate()
this.http = http;
}
// Angular2 DI desugar'd
static get parameters() {
return [[Http]];
}
authenticate(username, password) {
this.http.get('/login');
}
}
Кроме того: я знаю, что это работает, потому что я использую его для компонента <ng2-markdown>
на EvanPlaice.com.
Ответ 2
Как я уже ответил на это здесь. Если вы пишете код в ES7, используйте static getter для свойства parameters
, чтобы указать инъекции в constructor
вашего компонент. Например:
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
}
Я думаю, что это самый сжатый метод в этот момент.
Помните, что в данный момент в ES7 нет предложения по поддержке декораторов параметров (например см. эту проблему для Babel).
Ответ 3
Метод из официального API Review работает для меня:
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);
}
}
Ответ 4
С babel-plugin-angular2-annotations вы можете добавлять сервисы с помощью аннотаций типа параметра конструктора точно так же, как TypeScript.
Установите плагины babel:
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"
]
}
и вуаля!
import {Component, 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(http: Http) {
console.log('http', http);
this.http = http;
}
authenticate(username, password) {
this.http.get('/login');
}
}
Обратите внимание, что подпись типа используется только для подсказки для инъекции зависимостей и не используется для проверки типов.