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

コンポーネントを手動で更新する必要はありません。あなたがやっているとは思わないコンポーネント内の 'ChangeDetectorRef'の参照を使っていない限り、強制的に実行する['Application.tick()'](https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html#!#tick-anchor)メソッドを試すことができます変更の検出を実行するが、私はこれがあなたを助けることを疑う。私はデータが異なる構造をしていると思います。それを '{{line | json}} '。 – martin

関連する問題