#angular #typescript
#angular #typescript
Вопрос:
У меня есть сервис в Angular 2 с использованием TypeScript. Я хочу иметь возможность совместно использовать массив значений, которые я получаю от этого сервиса. когда один компонент вносит изменения в массив, мне нужно, чтобы это было отражено в другом компоненте.
Это основы моего сервиса и объекта, который он использует
export class deviceObj {
device_Id:number;
deviceGroup_Id:number;
name:string;
favoriteFlag:boolean;
visibleFlag:boolean;
}
export class Favorite {
favorite_Id: number;
device: deviceObj;
constructor(){this.device = new deviceObj()};
}
@Injectable()
export class FavoriteService {
private headers = new Headers({'Content-Type': 'application/json'});
private favoritesURL = 'URL THAT FEETCHES DATA';
favorites: Favorite[];
constructor(private http: Http) {
this.getFavorites().then(favorites => this.favorites = favorites);
}
getFavorites(): Promise<Favorite[]> {
return this.http.get(this.favoritesURL).toPromise().then(response => response.json() as Favorite[]).catch(this.handleError);
}
protected handleError2(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'server error');
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); //
return Promise.reject(error.message || error);
}
}
И вот один из компонентов, который получает массив избранных.
import {FavoriteService} from'../../services/favorite/favorite.service';
declare var jQuery: any;
@Component({
selector: '[sidebar]',
directives: [
ROUTER_DIRECTIVES,
SlimScroll
],
template: require('./sidebar.html')
})
export class Sidebar implements OnInit {
constructor(config: ConfigService, el: ElementRef, router: Router, location: Location,
private favoriteService:FavoriteService) {
}
getFavorites(): void{
this.favoriteService
.getFavorites()
.then(favorites => this.favorites = favorites);
}
В каждом компоненте, использующем сервис, у него есть свой собственный массив избранного, который назначается при загрузке. Однако мне нужна одноэлементная переменная в сервисе, где изменения могут быть отражены в двух компонентах. Я не уверен, как это сделать с promises. Я рад уточнить, если это необходимо. Любая помощь будет высоко оценена.
Комментарии:
1. В вашем компоненте получите / установите массив избранного из модели сервиса. this.favoriteService.favorites будет работать как одноэлементный.
2. @user32 Если я создам метод get, он вернется до того, как обещание будет выполнено. как мне сделать так, чтобы она возвращалась при успешном выполнении обещания?
Ответ №1:
Хотя это, вероятно, можно сделать с помощью обещаний, я могу ответить в виде наблюдаемых, по крайней мере, если вы хотите прочитать о них…
Дано ComponentA
, и ComponentB
оба смотрят на a SharedService
для их источника SomeObject[]
данных:
Сервис:
import { Injectable } from '@angular/core';
import { Observable, Observer } from 'rxjs/rx';
import 'rxjs/add/operator/share';
import { SomeObject } from './some-object';
@Injectable()
export class SomeService{
SharedList$: Observable<SomeObject[]>;
private listObserver: Observer<SomeObject[]>;
private sharedList: SomeObject[];
constructor(private http: Http){
this.sharedList = [];
this.SharedList$ = new Observable<SomeObject[]>(x => this.listObserver = x).share();
}
getList(){
// Get the data from somewhere, i.e. http call
this.http.get(...)
.map(etc)
.subscribe(res => {
this.sharedList = res;
this.listObserver.next(this.sharedList);
});
// the important part is after getting the data you want, observer.next it
}
addItem(item: SomeObject): void {
this.sharedList.push(item);
this.listObserver.next(this.sharedList);
}
}
Компоненты затем имеют:
import { Component, OnInit } from '@angular/core';
import { Observable, Observer } from 'rxjs/rx';
import { SharedService } from './some.service';
import { SomeObject } from './some-object';
@Component({...})
export class CommponentA implements OnInit {
private list: SomeObject[];
constructor(private service: SharedService){
this.list = [];
}
ngOnInit(){
this.service.SharedList$.subscribe(lst => this.list = lst);
this.service.getList();
}
private onClick(item: SomeItem): void {
this.service.addItem(item);
}
}
ComponentB
будет выглядеть аналогично — подписка на одно и то же SharedList$
свойство в сервисе. Когда getList()
вызывается метод сервиса и он передает новое SomeObject[]
значение через observables ( this.listObserver.next(..)
) , компоненты, подписанные на это свойство, смогут считывать переданное ему значение.
Редактировать: предоставил addItem
метод в сервисе, который компоненты могут вызывать для добавления элементов в список. Затем сервис передает его через observable, ( this.listObserver.next(...)
) в том же стиле, что и при получении данных с помощью другого метода (т.Е. http).
Комментарии:
1. Я попробую это и сообщу
2. Итак, вот где я застрял сейчас. Как мне добавить элемент в SharedList $ или listObserver? итак, если для одного компонента мне нужно добавить другой объект, как мне это сделать?
3. Чтобы добавить переменную в список, которым делится моя служба, нужно ли мне немедленно сохранить в базе данных и снова получить этот список? Я хочу иметь возможность сделать что-то подобное в компоненте a
addToList(SomeObject ){ this.service.addToList(SomeObject) }
, а затем отобразить этот объект в компоненте B. В этом весь смысл наличия сервиса. Я мог бы просто восстановить эти значения по отдельности в каждом компоненте в противном случае.4. @Точно ничего. Я обновлю свой ответ, чтобы вы включили это.
5. Редактировать неважно, я заставил это работать. это была проблема с импортом, потребовалась эта строка
import { Observable, Observer } from 'rxjs/Rx';
, большое спасибо, что вы меня спасли. Я отмечу ваш ответ как правильный.
Ответ №2:
Ответ @Krenom был правильным. с одним импортом, который необходимо изменить в моей настройке.
Мне нужно было import { Observable, Observer } from 'rxjs/Rx';import { Observable, Observer } from 'rxjs/Rx';
Ответ №3:
В вашем компоненте
//set favorites
getFavorites(): void{
this.favoriteService
.getFavorites()
.then(favorites => this.favoriteService.favorites = favorites);
}
// get favorite
this.favorites = this.favoriteService.favorites;//access it from service
Комментарии:
1. Похоже, это создает копию, а не передает ссылку. Таким образом, он становится пустым до завершения обещания