Reputation: 131
I was trying to get the items from my shopping cart in another component so I can display them. This is what I did:
I injected the cartService and got the cart:
export class CheckoutReviewComponent implements OnInit {
cart$: Observable<ICartModel>;
constructor(private cartService: CartService) { }
ngOnInit(): void {
this.cartService.cart$ = this.cart$;
}
}
In the html folder I looped over the items to display them:
<div class="items" *ngFor="let item of (cart$|async).items">
<div class="product">
**display
</div>
</div>
In the console I get an error saying "Cannot read property 'items' of null". So I did not get them correctly. In the other component everything is working well. So what should I do to get them from the other component?
CartService:
export class CartService {
url = 'https://localhost:5001/api/'
private cartBS = new BehaviorSubject<ICartModel>(null);
private totalBS = new BehaviorSubject<ICartTotal>(null);
cart$ = this.cartBS.asObservable();
total$ = this.totalBS.asObservable();
constructor(private http: HttpClient) { }
getCart(id: string) {
return this.http.get(this.url + 'cart?cartId=' + id).pipe(
map((cart: ICartModel)=> {
this.cartBS.next(cart);
this.calculateTotal();
})
);
}
updateCart(cart: ICartModel) {
return this.http.post(this.url + 'cart', cart).subscribe(
(response: ICartModel)=>{
this.cartBS.next(response);
this.calculateTotal();
}, error => console.log(error)
);
}
deleteCart(cart: ICartModel) {
return this.http.delete(this.url + 'cart?cartId=' + cart.id).subscribe(() => {
this.cartBS.next(null);
this.totalBS.next(null);
localStorage.removeItem('cart_id'); },
error => console.log(error) );
}
incrementQuantity(item: ICartItem) {
const cart = this.cartBS.value;
const itemIndex = cart.items.findIndex(x => x.id === item.id);
cart.items[itemIndex].quantity++;
this.updateCart(cart);
}
decrementQuantity(item: ICartItem) {
const cart = this.cartBS.value;
const itemIndex = cart.items.findIndex(x => x.id === item.id);
if(cart.items[itemIndex].quantity > 1) {
cart.items[itemIndex].quantity--;
this.updateCart(cart);
} else {
this.removeItem(item);
}
}
removeItem(item: ICartItem) {
const cart = this.cartBS.value;
if ( cart.items.some(x => x.id === item.id ) ) {
cart.items = cart.items.filter(i => i.id !== item.id);
if ( cart.items.length > 0) {
this.updateCart(cart);
} else {
this.deleteCart(cart);
}
}
}
addToCart(item: IGemModel, quantity = 1) {
const itemAdded: ICartItem = this.mapGemToCartItem(item, quantity);
const cart = this.cartBS.value ?? this.createCart();
const itemIndex = cart.items.findIndex(i=> i.id === itemAdded.id);
if(itemIndex === -1 ){
cart.items.push(itemAdded);
}
else {
cart.items[itemIndex].quantity += quantity;
}
this.updateCart(cart);
}
mapGemToCartItem(item: IGemModel, quantity: number): ICartItem {
return {
id: item.id,
name: item.name,
price: item.price,
quantity: quantity,
picture: item.picture
};
}
private createCart(){
const cart = new Cart();
localStorage.setItem('cart_id', cart.id);
return cart;
}
private calculateTotal() {
const cart = this.cartBS.value;
const shipping =0;
const subtotal = cart.items.reduce((a,b)=> (b.price * b.quantity) + a, 0);
const total = subtotal + shipping;
this.totalBS.next({shipping, subtotal, total});
}
}
Upvotes: 1
Views: 202
Reputation: 14750
The problem is here:
private cartBS = new BehaviorSubject<ICartModel>(null);
You are sending an initial value of null
, which your component receives.
You could either initialize to empty cart object instead of null
:
private cartBS = new BehaviorSubject<ICartModel>({items: []});
Or you can filter in your component:
this.cart$ = this.cartService.cart$.pipe(filter(c => !!c));
Upvotes: 1