I need advice on how to make observable variable currentShop
dependent on variable shopList
.
我需要有关如何根据变量shopList创建可观察变量currentShop的建议。
AppComponent
reads shopList
through shopProvider
. It works without a problem, but I need to modify the code to set currentShop
from loaded shops.
AppComponent通过shopProvider读取shopList。它没有问题,但我需要修改代码以从加载的商店设置currentShop。
Thanks.
谢谢。
AppComponent:
AppComponent:
export class AppComponent {
currentShop;
shopList;
constructor(router: Router,shopProvider:ShopProvider){
this.shopList = shopProvider.shops;
this.currentShop = shopProvider.currentShop;
shopProvider.loadShops();
shopProvider.setCurrentShop(-1);
router.navigate(['/System']);
}
}
ShopProvider:
ShopProvider:
export class ShopProvider{
private _http:Http;
shops:Observable<Array<Shop>>;
currentShop:Observable<Shop>;
private obServer:any;
private _shopDataStore : {
shops: Array<Shop>
}
constructor(http:Http){
this._http = http;
this.shops = new Observable(observer => this.obServer = observer).share();
//this.currentShop = ??
this._shopDataStore = {shops: []};
}
setCurrentShop(shopId:number){
//Code ??
}
loadShops(){
this._http
.get('/services/shop/list')
.map(res => res.json())
.subscribe(data => {
this._shopDataStore.shops = data;
this.obServer.next(this._shopDataStore.shops);
})
}
}
HTML:
HTML:
<div>{{currentShop.name | async}}</div>
<ul>
<li *ngFor="#shop of shopList | async">
<a [routerLink]="['/Shop', {shopId: shop.id}]">
<span>{{shop.name}}</span>
</a>
</li>
</ul>
2 个解决方案
#1
3
I would go for an architecture more similar to:
我会选择一个更类似于以下的架构:
ShopService
ShopService
class Shop {
constructor(public shopId: Number, public shopName: string) {}
}
@Injectable()
class ShopService {
shops: Observable<Array<Shop>> = new Observable<Array<Shop>>();
shopId: Subject<Number> = new Subject<Number>();
currentShop: Observable<Shop> = new Observable<Shop>();
public static getShopById(shops: Array<Shop>, shopId: Number): Shop {
return shops.filter(shop => shop.shopId === shopId)[0];
}
public static compareShops(oldShop: Shop, newShop: Shop): Boolean {
return oldShop.shopId === newShop.shopId;
}
constructor(@Inject(Http) private http: Http) {
this.shops = this.http
.get('**url here**')
.map(res => res.json().shops);
this.currentShop = this.shops
.combineLatest(this.shopId, ShopService.getShopById)
.distinctUntilChanged(ShopService.compareShops);
}
setCurrentShop(shopId: Number): void {
this.shopId.next(shopId);
}
}
Usage in your Component
:
组件中的用法:
- save
ShopService.currentShop
to a variable in theComponent
(let's saythis.currentShop
- 将ShopService.currentShop保存到Component中的变量(比如说this.currentShop
- use
{{ currentShop | async }}
or.subscribe()
to theShopService.currentShop
observable to be given the shop when it changes - 使用{{currentShop | async}}或.subscribe()到ShopService.currentShop observable,当它发生变化时给予商店
See a working example on CodePen. I like this approach more because I'm not saving any state, which seems more in line with reactive programming.
查看CodePen上的工作示例。我更喜欢这种方法,因为我没有保存任何状态,这似乎更符合反应式编程。
#2
1
I suggest the following:
我建议如下:
ShopProvider
ShopProvider
private shopsObserver:Observer<Shop[]>;
private currentShopObserver: Observer<Shop>;
private _shopDataStore : {
shops: [],
currentShop: undefined
}
constructor(http:Http){
this._http = http;
this.shops = new Observable(observer => this.obServer = observer).share();
this.currentShop = new Observable(observer => this.shopObserver = observer).share();
}
setCurrentShop(shopId:number){
var item = this._shopDataStore.shops.find(item=>item.shopId == shopId);
this._shopDataStore.currentShop = item;
this.currentShopObserver.next(this._shopDataStore.currentShop);
}
loadShops(){
this._http
.get('/services/shop/list')
.map(res => res.json())
.subscribe(data => {
this._shopDataStore.shops = data;
this.shopsObserver.next(this._shopDataStore.shops);
})
}
AppComponent
AppComponent
export class AppComponent {
currentShop;
shopList;
constructor(router: Router,shopProvider:ShopProvider){
shopProvider.shops.subscribe(shops=>this.shopList = shops);
shopProvider.currentShop.subscribe(currentShop => this.currentShop = currentShop);
shopProvider.loadShops();
shopProvider.setCurrentShop(-1);
router.navigate(['/System']);
}
}
HTML
HTML
<div>{{currentShop?.name}}</div>
<ul>
<li *ngFor="#shop of shopList">
<a [routerLink]="['/Shop', {shopId: shop.id}]">
<span>{{shop.name}}</span>
</a>
</li>
</ul>
#1
3
I would go for an architecture more similar to:
我会选择一个更类似于以下的架构:
ShopService
ShopService
class Shop {
constructor(public shopId: Number, public shopName: string) {}
}
@Injectable()
class ShopService {
shops: Observable<Array<Shop>> = new Observable<Array<Shop>>();
shopId: Subject<Number> = new Subject<Number>();
currentShop: Observable<Shop> = new Observable<Shop>();
public static getShopById(shops: Array<Shop>, shopId: Number): Shop {
return shops.filter(shop => shop.shopId === shopId)[0];
}
public static compareShops(oldShop: Shop, newShop: Shop): Boolean {
return oldShop.shopId === newShop.shopId;
}
constructor(@Inject(Http) private http: Http) {
this.shops = this.http
.get('**url here**')
.map(res => res.json().shops);
this.currentShop = this.shops
.combineLatest(this.shopId, ShopService.getShopById)
.distinctUntilChanged(ShopService.compareShops);
}
setCurrentShop(shopId: Number): void {
this.shopId.next(shopId);
}
}
Usage in your Component
:
组件中的用法:
- save
ShopService.currentShop
to a variable in theComponent
(let's saythis.currentShop
- 将ShopService.currentShop保存到Component中的变量(比如说this.currentShop
- use
{{ currentShop | async }}
or.subscribe()
to theShopService.currentShop
observable to be given the shop when it changes - 使用{{currentShop | async}}或.subscribe()到ShopService.currentShop observable,当它发生变化时给予商店
See a working example on CodePen. I like this approach more because I'm not saving any state, which seems more in line with reactive programming.
查看CodePen上的工作示例。我更喜欢这种方法,因为我没有保存任何状态,这似乎更符合反应式编程。
#2
1
I suggest the following:
我建议如下:
ShopProvider
ShopProvider
private shopsObserver:Observer<Shop[]>;
private currentShopObserver: Observer<Shop>;
private _shopDataStore : {
shops: [],
currentShop: undefined
}
constructor(http:Http){
this._http = http;
this.shops = new Observable(observer => this.obServer = observer).share();
this.currentShop = new Observable(observer => this.shopObserver = observer).share();
}
setCurrentShop(shopId:number){
var item = this._shopDataStore.shops.find(item=>item.shopId == shopId);
this._shopDataStore.currentShop = item;
this.currentShopObserver.next(this._shopDataStore.currentShop);
}
loadShops(){
this._http
.get('/services/shop/list')
.map(res => res.json())
.subscribe(data => {
this._shopDataStore.shops = data;
this.shopsObserver.next(this._shopDataStore.shops);
})
}
AppComponent
AppComponent
export class AppComponent {
currentShop;
shopList;
constructor(router: Router,shopProvider:ShopProvider){
shopProvider.shops.subscribe(shops=>this.shopList = shops);
shopProvider.currentShop.subscribe(currentShop => this.currentShop = currentShop);
shopProvider.loadShops();
shopProvider.setCurrentShop(-1);
router.navigate(['/System']);
}
}
HTML
HTML
<div>{{currentShop?.name}}</div>
<ul>
<li *ngFor="#shop of shopList">
<a [routerLink]="['/Shop', {shopId: shop.id}]">
<span>{{shop.name}}</span>
</a>
</li>
</ul>