I am starting to play with the BehaviorSubject in Rxjs with limited experience in this area. So far I am able to get the root level parameters in the component, but accesing nested objects results in 'cannot read property x of undefined'.
Classes:
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())
);
}
Template (snippet)
<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>
If I remove the references of deeply nested objects, I get the expected results returned.
I am trying to use a BehaviorSubject to update several components, but not sure if this is even the best solution!
The code looks fine to me, I guess by "deep nested" you mean for example line.Product.Code
. If it works with line.Quantity
then the problem is most likely not in BehaviorSubject
but in the structure of your data.
I don't know what's your particular use-case but you don't need to use neither BehaviorSubject
nor async
pipe at all.
For BasketService
you can use just:
export class BasketService {
lines: BasketLine[];
// ...
loadBasket() {
this.basketBackendService.GetBasket().subscribe(
response => {
this.lines = <BasketLine[]>response.json().basket.BasketLines;
},
error => console.log(error.text())
);
}
}
Then render it with just:
<tr *ngFor="let line of basketService.lines">
// ...
</tr>