2016-08-15 84 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