javascript - TypeError: "ctx.cart no está definido"
Estoy trabajando en una aplicación de pedidos de pizza y actualmente estoy intentando implementar el carrito.
Tengo un carrito para cada usuario, y cada carrito contiene los siguientes detalles: cart.ts
import { CartItem } from './cartitem';
export class Cart {
id: string;
user: string;
cartitems: CartItem[];
grand_total: number;
}
El usuario puede agregar artículos del menú, que se convertirán en los artículos de mi carrito: cartitem.ts
import { Topping } from './topping';
export class CartItem {
id: string;
name: string;
baseprice: number;
toppings: Topping[];
extraprice: number;
quantity= 1;
total: number;
}
Así que al agregar un artículo al carrito, estoy haciendo una solicitud PUT en el endpoint de la API en el carrito del usuario, para poner el artículo en el carrito, y en respuesta, estoy devolviendo el contenido del carrito desde allí.
Así es como se ve mi cart.component.ts:
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);
});
});
}
}
Ahora el problema aquí es que no puedo enlazar los datos en el lado de cart.component.html con 'cart', genera este error: ERROR TypeError: "ctx.cart es indefinido".
No tengo ni idea de cómo arreglar esto.
Editar: Aquí está el 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>
y registro de errores:
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
Respuesta #1
El HTML agregado muestra el error en la línea 2 del HTML
<div>{{cart.user}}</div>
cart se define como en tu archivo TS
cart: Cart;
El valor interpolado cart.user no está disponible ya que cart en sí está indefinido en el momento de la inicialización. cart se completa más tarde cuando la suscripción se resuelve.
Una solución rápida podría ser envolver esto en un ng-container y usar *ngIf en él.
<ng-container *ngIf="cart">
<h2...
...
</div>
</ng-container>
Esto no mostrará nada hasta que se resuelva el carrito.
Sin embargo, en términos de mejor calidad de código, reemplaza todas tus interpolaciones con getters en TS
get cartUser() { return (cart && cart.user) ? cart.user : null }
Ahora tu HTML será así
<div>{{cartUser}}</div>
De la misma manera, obtendrás un error para cart.cartitems. Usa este getter
get cartCartitems() { return (cart && cart.cartitems) ? cart.cartitems : [] }
y reemplaza todas las instancias de cart.cartitems con cartCartitems en tu HTML
¡Espero que ayude!
Respuesta #2
Resolví este problema con:
cart: Cart = {} as Cart;
en lugar de:
cart: Cart;
