I have a service in an Angular 2 using TypeScript. I want to be able to share an array of values that I get from that service. when one component makes a change to the array I need it to be reflected in another component.
This is the basics of my service and the object it uses
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);
}
}
And here is one of the components that gets the array of favorites.
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);
}
In each component that uses the service it has its own favorites array that gets assigned on load. However I want a singleton variable in the service where changes can be reflected in two components. I'm not sure how to do this with promises. I am happy to clarify further if needed. Any help would greatly be apreciated.
While it can probably be done with Promises, I can answer in the form of Observables at the very least, if you're of a mind to read about them...
Given ComponentA and ComponentB both looking at a SharedService for their source of SomeObject[] data:
The service:
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);
}
}
Components then have:
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 would look similar - subscribing to the same SharedList$ property on the service. When the service's getList() method is called, and it pushes a new SomeObject[] through the observables (this.listObserver.next(..)), the components subscribed to that property will be able to read the value pushed to it.
Edit: Exposed an addItem method on the service that the components can call to push items to the list. The service then pushes it through the observable, (this.listObserver.next(...)) in the same style as when getting the data through x other method (i.e. http).
@Krenom's answer was corrrect. with one import needing to be changed on my setup.
I needed import { Observable, Observer } from 'rxjs/Rx';import { Observable, Observer } from 'rxjs/Rx';
In your component
//set favorites
getFavorites(): void{
this.favoriteService
.getFavorites()
.then(favorites => this.favoriteService.favorites = favorites);
}
// get favorite
this.favorites = this.favoriteService.favorites;//access it from service
来源:https://stackoverflow.com/questions/39897670/how-can-i-create-a-variable-in-a-service-that-gets-its-data-from-a-promise-yet-i