Я думаю, что я неправильно использую подписчика BehaviorSubject. Может ли кто-нибудь показать мне лучший способ вызова данных из моего API в Angular2?
У меня есть пара кнопок навигации в приложении Angular. Я пытаюсь удалить "Предыдущая" на первой странице и "Следующая" на последней.
Все, что я хочу сделать, это установить два логических значения, которые говорят, будет ли это первая или последняя страница.
Беда в том, что мне не удалось разобраться с этими subscribers
а также behaviours
,
Я могу создать функцию, которая рассчитывает последнюю страницу из totalItems
а также itemsPerPage
так что, пожалуйста, не беспокойтесь об этом, я просто не знаю, как вызвать функцию из этой подписки.
Если кто-то может показать мне, как написать обратный звонок или что-то еще, что нужно для этого, я буду вечно благодарен.
Component.html:
<div class="pagination-panel clearfix">
<button (click)="previousPage()" *ngIf="firstPage != true">Prev</button>
<button (click)="nextPage()" *ngIf="lastPage != true">Next</button>
</div>
<!-- How the data is used, if that helps -->
<h2 class="spray-header">Presenters</h2>
<article *ngFor="let presenter of (presenters$ | async)?.data" class="presenter-item">
<div class="presenters-header">
<h3 class="presenters-title margin-none">
<a [routerLink]="['/presenters', presenter.id]">{{presenter.name | uppercase}}</a>
</h3>
<p class="presenters-details">{{presenter.details}}</p>
</div>
<img src="{{presenter.small_thumb}}" class="presenters-profile-picture profile-picture">
</article>
Component.ts
import {Component, OnInit, Inject} from '@angular/core';
import {Http} from "@angular/http";
import "rxjs/add/operator/map";
import {BehaviorSubject} from "rxjs/BehaviorSubject";
import {ActivatedRoute, Router} from "@angular/router";
export class PresentersComponent implements OnInit {
firstPage = true;
lastPage = false;
presenters$ = new BehaviorSubject([
{
data: {
id: 0,
name: "Loading...",
details: "Loading...",
small_thumb: "",
radio_shows: []
},
currentPage: 1,
itemsPerPage: 0,
totalItems: 0
}
]);
constructor(@Inject('api') private api,
private colorService: ColorService,
private http: Http,
private route: ActivatedRoute,
private router: Router) {
route.params
.map((p: any) => p.page)
.switchMap(page => http.get(api + '/presenters?page=' + page))
.map(res => res.json())
.subscribe(this.presenters$);
}
}
Обновление 1
Может ли что-то подобное работать?
console.log(x);
кажется, возвращает мне правильные данные, но теперь ни один из моих (presenters$ | async)?.data
все работает.
.subscribe(
function (x) {
console.log(x);
this.presenters$ = x;
},
null,
function () {
console.log("set the values here");
}
);
Обновление 2
Вышеуказанные разрывы, потому что this
относится к вызову функции (дух!), но я получаю ошибки при попытке использовать жирную стрелку, кто-нибудь знает, что я здесь делаю неправильно?
.subscribe(
x => this.presenters$ = x,
null,
function () {
console.log("set the values here");
}
);
Выше не бросает и ошибка, но все же async
не работает.
Ниже выдается эта ошибка: "Ошибка: InvalidPipeArgument:" [объект объекта] "для канала" AsyncPipe ""
.subscribe(res => {
this.presenters$ = res;
// Any other lines here.
});
По ссылке ниже, похоже, мне просто нужно удалить асинхронную трубу, позже сделаю снимок. Angular 4: InvalidPipeArgument: '[объект объекта]' для канала 'AsyncPipe'
Обновление 3
Удаляя асинхронный канал из вызова данных в шаблоне (presenters$ | async)?.data"
Я преодолел ошибку в последнем обновлении и смог получить функциональность после работы в среде разработчиков.
// component.html change
(presenters$)?.data
// latest subscribe that I have working, sort of
.subscribe(res => {
this.presenters$ = res
// got extras lines of code working here
});
Проблема сейчас в том, что не будет компилироваться для производства. Когда я пытаюсь скомпилировать, я получаю эту ошибку:
ОШИБКА в ng:///var/www/html/io->radio/src/app/ Presenters/views/ Presenters.component.html (2,1): Свойство>'data' не существует для типа 'BehaviorSubject< {данные: {id: номер; >имя: строка; детали: строка; small_thumb: строка; radio_s... '.
Обновление 4
Я начинаю думать, что я здесь полный дурак, и что BehaviorSubject
это не то, что я должен использовать. Все, что я пытаюсь сделать, это вызвать данные из моего API и сопоставить их с объектом, если кто-то может сказать мне, что я делаю неправильно, это было бы очень полезно.
Я думаю, что мои проблемы связаны с ненадлежащим использованием объекта BehaviorSubject и отсутствием понимания асинхронного канала.
Мой следующий шаг - опробовать очень разумное предложение от @DeborrahK и создать сервис для извлечения данных.
1 ответ
Хитрость заключается в том, чтобы добавить фигурные скобки вокруг нескольких строк кода. У меня есть пример ниже.
.subscribe(res => {
this.presenters$ = res;
// Any other lines here.
});
Но вы можете рассмотреть что-то вроде этого:
ngOnInit(): void {
this.route.params.subscribe(
params => {
const id = +params['id'];
this.getMovie(id);
// I could have more lines of code here.
}
);
}
Этот бит кода выполняется при инициализации компонента. Он следит за изменениями ваших параметров и получает разные данные при изменении параметров. Вы можете значительно упростить приведенный выше код, если параметры не меняются.
getMovie(id: number): void {
this.movieService.getMovie(id)
.subscribe(
movie => {
this.onMovieRetrieved(movie);
// I could have more lines of code here
},
error => {
this.errorMessage = <any>error;
// I could have more lines of code here
}
);
}
Этот код вызывает сервис для извлечения данных. subscribe()
это здесь. Http.get находится внутри сервиса.
При этом используются фильмы вместо имеющихся у вас данных, но концепции и структура будут такими же.
У меня есть полный пример здесь: https://github.com/DeborahK/MovieHunter