I'm working on pizza ordering app, and currently I'm trying to implement Cart.
I have a cart for every user, and each cart contains following details: cart.ts
import { CartItem } from './cartitem';
export class Cart {
id: string;
user: string;
cartitems: CartItem[];
grand_total: number;
}
User can add items from the menu, which will become my cart items: cartitem.ts
import { Topping } from './topping';
export class CartItem {
id: string;
name: string;
baseprice: number;
toppings: Topping[];
extraprice: number;
quantity= 1;
total: number;
}
So on adding an item to the cart, I'm making a PUT request on the API endpoint on the user cart, to put the cart item, and in response, I'm returning the cart contents from there.
Here's how my cart.component.ts looks:
import { Component, OnInit, ViewChild, Inject, Injector } from '@angular/core';
import { CartItem } from '../shared/cartitem';
import { ActivatedRoute } from '@angular/router';
import { CartService } from '../services/cart.service';
import { map, catchError } from 'rxjs/operators';
import { Cart } from '../shared/cart';
@Component({
selector: 'app-cart',
templateUrl: './cart.component.html',
styleUrls: ['./cart.component.scss']
})
export class CartComponent implements OnInit {
cart: Cart;
// cartitems: CartItem[];
constructor(
private route: ActivatedRoute,
private cartService: CartService,
@Inject('BaseURL')public BaseURL) { }
ngOnInit(): void {
this.updateCart();
}
updateCart() {
this.cartService.mysubject.subscribe((value) => {
console.log(value);
this.cartService.getItems().subscribe(response => {
console.log("Response in cart comp:", response);
let cartContent = new Cart();
cartContent.cartitems = response['cartitems'];
cartContent.id = response['id'];
cartContent.grand_total = response['grand_total'];
cartContent.user = response['user'];
this.cart = cartContent;
console.log("Cart is:", this.cart);
});
});
}
}
Now issue here is that I'm not able to bind the data on cart.component.html side with 'cart', it generates this error- ERROR TypeError: "ctx.cart is undefined".
I'm clueless on how to fix this.
Edit: Here is the cart.component.html:
<h2>Cart</h2>
<div>{{cart.user}}</div>
<mat-list dense>
<mat-list-item *ngFor="let cartitem of cart.cartitems">
<h2 matLine>Item: {{cartitem.name}}</h2>
<p matLine>Base Price: ${{cartitem.baseprice}}</p>
<p matLine [hidden]="cartitem.toppings == []">Extra Toppings:
<mat-list matLine>
<mat-list-item matLine *ngFor="let topping of cartitem.toppings">
<h4 matLine>{{topping.name}} : + ${{topping.rate}}</h4>
</mat-list-item>
</mat-list>
</p>
<button mat-mini-fab color="primary"><i class="fa fa-minus-circle"></i></button><div></div><button mat-mini-fab color="primary"><i class="fa fa-plus-circle"></i></button>
</mat-list-item>
</mat-list>
<div [hidden]="!cart.cartitems"><h2>Subtotal: ${{cart.grand_total}}</h2></div>
<div [hidden]="cart.cartitems">
<p> Your Cart is Empty!</p>
</div>
and error log:
ERROR TypeError: "ctx.cart is undefined"
CartComponent_Template cart.component.html:2
Angular 26
executeTemplate
refreshView
refreshComponent
refreshChildComponents
refreshView
refreshComponent
refreshChildComponents
refreshView
refreshDynamicEmbeddedViews
refreshView
refreshComponent
refreshChildComponents
refreshView
renderComponentOrTemplate
tickRootContext
detectChangesInRootView
detectChanges
tick
next
invoke
onInvoke
invoke
run
run
next
schedulerFn
RxJS 5
Angular 8
core.js:6185:19
The HTML added shows the error in line 2 of HTML
<div>{{cart.user}}</div>
cart
is defined as in your TS file
cart: Cart;
The interpolated value cart.user
is not available as cart
itself is undefined at time of init. cart
is populated later when subscription resolves.
A quick work-around maybe to wrap this in an ng-container
and use *ngIf
on it.
<ng-container *ngIf="cart">
<h2...
...
</div>
</ng-container>
This will not display anything till the cart
is resolved.
However, in terms of better code quality, replace all your interpolations with getters in the TS
get cartUser() { return (cart && cart.user) ? cart.user : null }
Now your HTML will be like
<div>{{cartUser}}</div>
Same way, you will get error for cart.cartitems
. Use this getter
get cartCartitems() { return (cart && cart.cartitems) ? cart.cartitems : [] }
and replace all instances of cart.cartitems
with cartCartitems
in your HTML
Hope it helps!