2016-08-15 3 views
1

Я начинаю играть с BehaviorSubject в Rxjs с ограниченным опытом работы в этой области. Пока я могу получить параметры корневого уровня в компоненте, но доступ к вложенным объектам приводит к тому, что «невозможно прочитать свойство x неопределенного».Rxjs включают глубоко вложенные объекты в behaviorsubject

Классы:

export class Basket extends X23Object { 
    public BasketId: number; 
    public UserID: number; 
    public User: User; 
    public BasketLines: BasketLine[] = []; 
} 

export class BasketLine extends X23Object { 
    public BasketLineId: number; 
    public BasketId: number; 
    public ProductId: number; 
    public Quantity: number; 
    public Product: Product; 
    public Price: number; 
    public Name: string; 
} 
export class Product extends X23Object { 
    public ProductId: number; 
    public CategoryId: number; 
    public Name: string; 
    public Code: string; 
    public Price: number; 
    public Details: string; 
    public Images: Image[]; 
    public Category: Category; 
} 

BasketBackendService

GetBasket() { 
    return this.authHttp.get(this.apiUrl + 'api/GetBasketByUser?id=' + parseInt(this.decodedJwt['userId']), { headers: contentHeaders }); 
} 

BasketService

private _lines: BehaviorSubject<BasketLine[]> = new BehaviorSubject([new BasketLine]); 
get getLines() { 
    return this._lines.asObservable(); 
} 
loadBasket() { 
    this.basketBackendService.GetBasket() 
     .subscribe(
      response => { 
       let lines = <BasketLine[]>response.json().basket.BasketLines; 

       this._lines.next(lines); 
      }, 
      error => console.log(error.text()) 
     ); 
} 

Шаблон (фрагмент)

<tr *ngFor="let line of basketService.getLines | async"> 
    <td><img class="login-logo" src="{{ line.Product.Images[0].ThumbUrl }}" width="100%" /></td> 
    <td><a [routerLink]="['Product', { id: line.ProductId }]"> {{ line.Product.Code }} </a></td> 
    <td><a [routerLink]="['Product', { id: line.ProductId }]">{{ line.Product.Name }}</a></td> 
    <td class="text-right">{{ line.Price | currency:'GBP':true:'.2-2' }}</td> 
    <td class="text-center">{{ line.Quantity }}</td> 
    <td class="text-right">{{ line.Quantity * line.Price | currency:'GBP':true:'.2-2' }}</td> 
    <td><button (click)="DeleteLine(line.BasketLineId)">Remove</button></td> 
</tr> 

Если я удалю ссылки на глубоко вложенные объекты, я получаю ожидаемые результаты.

Я пытаюсь использовать BehaviorSubject для обновления нескольких компонентов, но не уверен, что это даже лучшее решение!

ответ

0

Код выглядит хорошо для меня, я думаю, что «глубоко вложенным» вы имеете в виду, например, line.Product.Code. Если он работает с line.Quantity, тогда проблема может возникнуть, скорее всего, не в BehaviorSubject, но и в структуре ваших данных.

Я не знаю, каков ваш конкретный прецедент, но вам не нужно использовать ни BehaviorSubject, ни async трубы вообще.

Для BasketService вы можете использовать только:

export class BasketService { 
    lines: BasketLine[]; 

    // ... 

    loadBasket() { 
     this.basketBackendService.GetBasket().subscribe(
      response => { 
       this.lines = <BasketLine[]>response.json().basket.BasketLines; 
      }, 
      error => console.log(error.text()) 
     ); 
    } 
} 

Затем делают его просто:

<tr *ngFor="let line of basketService.lines"> 
    // ... 
</tr> 
+0

Проблема этого метода состоит в том, что он не обновляет другие компоненты. У меня есть компонент, который показывает корзину в заголовке, которая обновляет только обновленную страницу. Я искал подход к обслуживанию/теме, чтобы сделать данные корзины наблюдаемыми и обновить корзину во всех соответствующих компонентах, не обновляя страницу. –

+0

Похоже, что глубоко вложенные объекты могут отображаться как неопределенные, так как управление изменениями обновляет компоненты до того, как объекты будут готовы, но не все время –

+0

Вам не нужно обновлять какие-либо компоненты вручную, обнаружение изменений углов делает это для вам, если вы не играете с ссылками «ChangeDetectorRef» в своем компоненте, который, я думаю, вы не делаете. Вы можете попробовать запустить метод ['Application.tick()'] (https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html#!#tick-anchor), чтобы заставить его для запуска обнаружения изменений, но я сомневаюсь, что это поможет вам. Я думаю, что данные имеют другую структуру, чем вы ожидаете. Попробуйте сбросить его с помощью '{{line | }} JSON '. – martin

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