2016-01-18 4 views
0

Мне нужен совет о том, как сделать видимую переменную currentShop в зависимости от переменной shopList.Две наблюдаемые переменные, зависящие друг от друга

AppComponent читает shopList через shopProvider. Он работает без проблем, но мне нужно изменить код, чтобы установить currentShop из загруженных магазинов.

Спасибо.

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:

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:

<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> 

ответ

3

Я хотел бы пойти на дуге hitecture больше похож на:

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); 
    } 
} 

Использование в вашем Component:

  • сохранить ShopService.currentShop к переменной в Component (скажем this.currentShop
  • использования {{ currentShop | async }} или .subscribe() к наблюдаемый ShopService.currentShop для получения магазина при его изменении

См. рабочий пример на CodePen. Мне нравится этот подход больше, потому что я не сохраняю никакого состояния, которое, похоже, больше соответствует реактивному программированию.

+0

Благодарим вас за подробные инструкции! Но для меня это не работает. Это приложение не записывает ошибки. shopList все еще работает хорошо, но CurrentShop не появляется :(Если в компоненте будет использоваться js .subscribe (res => {console.log (res)}). Отображает {id: 1, name: 'Test'}. проблема в том, что он работает в компоненте и в шаблоне нет? Здесь полный код: http://pastebin.com/TZ0cwFJF – JaSHin

+0

Я бы также добавил, что мне нужно поместить некоторые журналы в код и отображать только «настройку». – JaSHin

+1

Я тоже столкнулся с этой проблемой.Если вы видите в моем примере, я передаю 'currentShop | async' на отдельный компонент. 'currentShop.name | async' пытается обрабатывать 'name' как наблюдаемое ... Не уверен, как сделать что-то вроде' (currentShop | async) .name'. Вы можете подписаться на «currentShop», наблюдаемый в вашем компоненте, и сохранить экземпляр «Shop' в другой переменной и использовать это ... –

1

Я предлагаю followin г:

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

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

<div>{{currentShop?.name}}</div> 

<ul> 
    <li *ngFor="#shop of shopList"> 
     <a [routerLink]="['/Shop', {shopId: shop.id}]"> 
      <span>{{shop.name}}</span> 
     </a> 
    </li> 
</ul> 
+0

Спасибо за помощь. Но я использовал код ниже: – JaSHin

+0

Не беспокойтесь, мне нравится решение, которое он предложил. – pixelbits

Смежные вопросы