5
votes

TypeError: "ctx.cart n'est pas défini"

Je travaille sur une application de commande de pizza et j'essaie actuellement de mettre en œuvre Cart.

J'ai un panier pour chaque utilisateur, et chaque panier contient les détails suivants: cart.ts

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

L'utilisateur peut ajouter des articles à partir du menu, qui deviendront les articles de mon panier: cartitem.ts

<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>

Donc, en ajoutant un article au panier, je fais une demande PUT sur le point de terminaison de l'API sur le panier de l'utilisateur, pour mettre l'article du panier, et en réponse, je retourne le contenu du panier à partir de là.

Voici à quoi ressemble mon 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);

      });
    });
  }

}

Maintenant, le problème ici est que je ne suis pas en mesure de lier les données sur le côté cart.component.html avec 'cart', cela génère cette erreur - ERROR TypeError: "ctx.cart is undefined".

Je ne sais pas comment résoudre ce problème.

Edit : Voici le cart.component.html:

import { Topping } from './topping';
export class CartItem {
    id: string;
    name: string;
    baseprice: number;
    toppings: Topping[];
    extraprice: number;
    quantity= 1;
    total: number;
}

et journal des erreurs:

import { CartItem } from './cartitem';

export class Cart {
    id: string;
    user: string;
    cartitems: CartItem[];
    grand_total: number;
}


2 commentaires

Comment essayez-vous de lier des données sur html? Veuillez également partager le journal des erreurs


@ T.SunilRao Bonjour, j'ai ajouté la partie html et les journaux d'erreurs dans la question


3 Réponses :


1
votes

Nous n'avons pas de contexte html où nous pouvons voir comment vous liez ctx , mais je suppose que cela est dû au fait que ctx n'existe pas dans votre composant et que vous essayez de vous y lier. Ce type d'erreur est généré lorsque vous accédez à une propriété d'objet qui n'est pas définie.

Par exemple:

this.cart = {
    cartitems: response['cartitems'],
    id: response['id'],
    grand_total : response['grand_total'],
    user : response['user ']
}

Essayez des valeurs de liaison en HTML comme ceci <div> {{ cart.id }}</div> et cela devrait fonctionner.

en passant, ce serait beaucoup plus facile et meilleur en termes de qualité de code si vous le faisiez comme ceci:

// now we dont need to explicitly instantiate new class
export interface Cart {
    id: string;
    user: string;
    cartitems: CartItem[];
    grand_total: number;
}

et dans le code, procédez comme suit

let someIncorrectObject = undefined;
someIncorrectObject.someValue // ERROR TypeError: "someIncorrectObject.someValue is undefined".


3 commentaires

Salut, j'ai ajouté la partie html dans la question, et je crois que ne pas utiliser "interface" au lieu de classe n'a rien à voir avec cette erreur, non?


vous avez raison, cela ne concerne que les meilleures pratiques, mais cela n'affecte pas le code.


noté, je chercherai à pratiquer de cette manière. Merci!



8
votes

Le HTML ajouté montre l'erreur à la ligne 2 du HTML

get cartCartitems() { return (cart && cart.cartitems) ? cart.cartitems : [] }

cart est défini comme dans votre fichier TS

<div>{{cartUser}}</div>

La valeur interpolée cart.user n'est pas disponible car le cart lui-même n'est pas défini au moment de l'initialisation. cart est rempli plus tard lorsque l'abonnement est résolu.

Une solution rapide peut-être pour envelopper cela dans un ng-container et utiliser *ngIf dessus.

get cartUser() { return (cart && cart.user) ? cart.user : null }

Cela n'affichera rien tant que le cart ne sera pas résolu.

Cependant, pour une meilleure qualité de code, remplacez toutes vos interpolations par des getters dans le TS

<ng-container *ngIf="cart">
  <h2...
  ...
  </div>
</ng-container>

Maintenant, votre HTML sera comme

cart: Cart;

De la même manière, vous obtiendrez une erreur pour cart.cartitems . Utilisez ce getter

<div>{{cart.user}}</div>

et remplacez toutes les instances de cart.cartitems par cartCartitems dans votre HTML

J'espère que cela aide!


2 commentaires

Hé, ça a aidé et ça a marché. Je n'ai jamais pensé que le panier n'était pas défini au moment de l'initialisation. Merci!


Bienvenue! Heureux d'avoir pu aider.



0
votes

J'ai résolu ce problème avec:

cart: Cart;

au lieu de:

cart: Cart = {} as Cart;


0 commentaires