2016-08-15 61 views
1

我开始在Rxjs中使用BehaviorSubject,但在这方面的经验有限。到目前为止,我能够获取组件中的根级别参数,但访问嵌套对象会导致'无法读取未定义的属性x'。Rxjs包含行为主体中的深层嵌套对象

类:

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中,而是在数据结构中。

我不知道你的特定用例是什么,但你根本不需要使用BehaviorSubjectasync管。

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

您不必手动更新任何组件,Angular的更改检测可以用于你除非你在摆弄组件中的ChangeDetectorRef引用,我认为你没有这样做。你可以尝试运行['Application.tick()'](https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html#!#tick-anchor)方法来强制它运行变化检测,但我怀疑这会帮助你。我认为数据具有不同的结构,然后您可以期待。试着用'{{line | JSON}}'。 – martin

相关问题