Search code examples
angulartypescriptngxs

ngxs Selector display data (nested json data)


So the problem is that i have object user with many other object inside..so its became a nestet array (as i will show you above) I made with ngxs the selectors to obdain data and use them in html code...but its imposible to get secondary arrays.

{
  "userProfile": {
    "id": 1,
    "firstname": "kevin",
    "lastname": "kevin",
    "email": "[email protected]",
    "phone": "6949647400",
    "cart": {
      "id": 6,
      "grandTotal": 1000,
      "cartItem": [
        {
          "id": 5,
          "quantity": 1,
          "totalPrice": 55.5,
          "product": {
            "id": 1,
            "name": "Vans Shoes",
            "price": 55.5
          }
        },
        {
          "id": 6,
          "quantity": 1,
          "totalPrice": 111,
          "product": {
            "id": 2,
            "name": "Nike Shoes",
            "price": 55.5
          }
        },
        {
          "id": 7,
          "quantity": 1,
          "totalPrice": 55.5,
          "product": {
            "id": 3,
            "name": "Volcom T-shirt",
            "price": 55.5
          }
        }
      ]
    },
    "username": "kevin",
    "password": "$2a$10$PITUkb3QoOCIbZSDO9xLzOdfKwM.H/sFp.pgYnfssi31LIn8WotW2",
    "roles": [
      {
        "id": 3,
        "name": "ROLE_ADMIN"
      }
    ]
  }
}

This is the array as i get from backend call...i want to display the cart{} array with products etc etc..

import { Component, OnInit } from '@angular/core';
import { Cart } from 'src/app/core/interfaces/cart';
import { CartState} from './state/cart.state';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { UserProfile } from 'src/app/core/interfaces/userProfile';
import { ProfileState } from 'src/app/pages/profile/state/profile.state';
import { GetCart, } from './state/cart.action';

export class UserProfile {
  id!: number;
  username!: string ;
  password!: string ;
  email!:string;
  firstname!: string ;
  lastname!: string ;
  roles!: Roles;
  token!: string ;
  cart!:Cart[];
}


@Component({
  selector: 'app-cart',
  templateUrl: './cart.component.html',
  styleUrls: ['./cart.component.css'],
})
export class CartComponent implements OnInit {
  userId! :number;
  cartId! :number;
  cart! :any[];


  @Select(ProfileState.userProfile) userProfile$!: Observable<UserProfile>;
  
  @Select(CartState.cart)cart$!: Observable<Cart>;

  constructor(private store:Store) {}

  ngOnInit(){
    this.userProfile$.subscribe(userProfileData => {
      this.userId = userProfileData.id
     });
      this.store.dispatch(new GetCart(this.userId)).subscribe(response => {
        this.cart = response;
     })
  }
}


Solution

  • Firstly, your UserProfile class should be an interface instead of class.

    Secondly, userProfileData.cart is not an array. It is an object with properties: id: number, grandTotal: number and cartItem: SomeCartItem[].

    Then you need to subscribe to your cart @Select(CartState.cart) properly and dispatch your action only when you get the userId. And don't forget to unsubscribe() from your Observables.

    Here is an example:

    // your-component.ts
    public ngOnInit(): void {
      this.userProfile$.subscribe(userProfileData => {
        this.userId = userProfileData.id
    
        this.store.dispatch(new GetCart(this.userId));
      });
    
      this.cart$.subscribe(cart => {
        this.cart = cart;
        // here you will be able to retrieve your cartItems from the cart object
      });
    }
    
    public ngOnDestroy(): void {
      this.userProfile$.unsubscribe();
      this.cart$.unsubscribe();
    }