skip to Main Content

I want to display data that I retrieve in JSON format in my Angular V.17 html component. However, it is not displayed in my table even though I have them in the console. I don’t understand.
Indeed, when I arrive on the products page, I should have the "onGetAllProducts()" method called, which calls the service and its getAllProducts() method. Given that I have 5 products in my json database (db.json), the condition is respected and the data should be displayed. I retrieve them in console but not in html.

<nav class="navbar navbar-expand-sm bg-light navbar-light">
<ul class="navbar navbar-nav">
  <li>
    <button (click)="onGetAllProducts()" class="btn btn-outline-info">All</button>
  </li>
  <li>
    <button  (click)="onGetSelectedProducts()" class="btn btn-outline-info ">Selected</button>
  </li>
  <li>
    <button  (click)="onGetAvailableProducts()" class="btn btn-outline-info">Available</button>
  </li>
</ul>
  <ul class="navbar-nav m-lg-auto">
    <li>
<!--      f: represente les donnees totales du formulaire-->
      <form #f="ngForm" (ngSubmit)="onSearch(f.value)" class="form-inline">
          <input  ngModel name="keyword" type="text">
          <button class=" btn btn-outline-info ml-2">
          <span class=" fa fa-search"></span>
          </button>
      </form>
    </li>
  </ul>
</nav>
<div class="container">
  <ng-container *ngIf="products$|async as result"[ngSwitch]="result.data">
    {{result.dataState}}
    <ng-container *ngSwitchCase="DataStateEnum.LOADING" >
      Loading...
    </ng-container>
    <ng-container *ngSwitchCase="DataStateEnum.ERROR" >
      <div class="alert-danger">
        {{result.errorMessage}}
      </div>
    </ng-container>
    <ng-container *ngSwitchCase="DataStateEnum.LOADED" >
      <table class="table">
        <tr>
          <th>ID</th><th>Name</th><th>price</th><th>quantity</th><th>Selected</th><th>available</th>
        </tr>
        <tr *ngFor="let p of result.data">
          <td>{{p.id}}</td>
          <td>{{p.name}}</td>
          <td>{{p.price}}</td>
          <td>{{p.quantity}}</td>
          <td>{{p.selected}}</td>
          <td>{{p.available}}</td>
          <td>
          <button [ngClass]="p.selected?'btn-success':'btn-danger'" (click)="onSelect(p)">
            <span *ngIf="p.selected">UnSelect</span>
            <span *ngIf="!p.selected">Select</span>
          </button>
          </td>
          <td>
            <button class="btn btn-danger" (click)="onDelete(p)">
              <span  class="fa fa-trash-o">Delete</span>
            </button>
          </td>
        </tr>
      </table>
    </ng-container>
  </ng-container>
</div>

import {Component, OnInit} from '@angular/core';
import {ProductsService} from "../../services/products.service";
import {ProductModel} from "../../model/product.model";
import {catchError, map, Observable, of, startWith} from "rxjs";
import {AppDataState, DataStateEnum} from "../../../../state/stateProducts";



@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrl: './products.component.css'
})
export class ProductsComponent implements OnInit{
  //type observable mettre un $ a la fin pour le signaler et il faut faire un subscribe pour recuperer data d'un Observable
  products$: Observable<AppDataState<ProductModel[]>> |undefined;//ou |null=null ou products? : 2 autres facons de mentionner que la var n'a pas de valeur par defaut
  readonly DataStateEnum=DataStateEnum;

  constructor(private productService:ProductsService){}

  ngOnInit(): void {

  }
  onGetAllProducts(){
     this.products$ = this.productService.getAllProducts().pipe(
       map(data=>{
         console.log(data);
         return ({ dataSate:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
       startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
    catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
  }

 // protected readonly json = json;
  onGetSelectedProducts() {
    this.products$ = this.productService.getSelectedProducts().pipe(
      map(data=>{
        console.log(data);
        return ({ dataSate:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
      startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
      catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
  }

  onGetAvailableProducts() {
    this.products$ = this.productService.getAvailableProducts().pipe(
      map(data=>{
        console.log(data);
        return ({ dataSate:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
      startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
      catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
  }

  onSearch(dataForm: any) {
    this.products$ = this.productService.searchProducts(dataForm.keyword).pipe(
      map(data=>{
        console.log(data);
        return ({ dataSate:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
      startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
      catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
  }

  onSelect(p: ProductModel) {
this.productService.select(p).subscribe(data=>{p.selected=data.selected})
  }

  onDelete(p: ProductModel) {
    this.productService.deleteProduct(p).subscribe(data=>{this.onGetAllProducts()})
  }
}
import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {environment} from "../../environments/environment";
import {Observable} from "rxjs";
import {ProductModel} from "../model/product.model";

@Injectable({providedIn:"root"})
export class ProductsService{
constructor(private http:HttpClient) {
}
  getAllProducts():Observable<ProductModel[]>{
    let host=environment.host;
    return this.http.get<ProductModel[]>(host+"/products")
  }

  getSelectedProducts():Observable<ProductModel[]>{
    let host=environment.host;
    return this.http.get<ProductModel[]>(host+"/products?selected=true");
  }
  getAvailableProducts():Observable<ProductModel[]>{
    let host=environment.host;
    return this.http.get<ProductModel[]>(host+"/products?available=true");
  }
  searchProducts(keyword:string):Observable<ProductModel[]>{
    let host=environment.host;
    return this.http.get<ProductModel[]>(host+"/products?name_like="+keyword);
  }
  select(product:ProductModel):Observable<ProductModel>{
    let host=environment.host;
    product.selected=!product.selected;
    return this.http.put<ProductModel>(host+"/products/"+product.id,product);
  }
  deleteProduct(product:ProductModel):Observable<void>{//ne retourne rien donc :void
    let host=environment.host;
    product.selected=!product.selected;
    return this.http.delete<void>(host+"/products/"+product.id);
  }
}
export enum DataStateEnum{
  LOADING,
  LOADED,
  ERROR
}

export interface AppDataState<T> {
  dataState?: DataStateEnum,//1 des 3 val de l'enum
  data?:T,//data a afficher
  errorMessage?:string//nature du message: string

}
{
  "products": [
    {
      "id": 1,
      "name": "computer",
      "price": 4300,
      "quantity": 600,
      "selected": true,
      "available": true
    },
    {
      "id": 2,
      "name": "printer",
      "price": 300,
      "quantity": 100,
      "selected": true,
      "available": true
    },
    {
      "id": 3,
      "name": "smartphone",
      "price": 1200,
      "quantity": 200,
      "selected": true,
      "available": false
    },
    {
      "id": 4,
      "name": "juin",
      "price": 2000,
      "quantity": 500,
      "selected": false,
      "available": true

    },
    {
      "id": 5,
      "name": "souris",
      "price": 50,
      "quantity": 200,
      "selected": false,
      "available": false
    }
  ]
}

component.ts

enter image description here
console
console View:
(5) [{…}, {…}, {…}, {…}, {…}] 0
:
{id: 1, name: ‘computer’, price: 4300, quantity: 600, selected: true, …}
1
:
{id: 2, name: ‘printer’, price: 300, quantity: 100, selected: true, …}
2
:
{id: 3, name: ‘smartphone’, price: 1200, quantity: 200, selected: true, …}
3
:
{id: 4, name: ‘juin’, price: 2000, quantity: 500, selected: false, …}
4
:
{id: 5, name: ‘souris’, price: 50, quantity: 200, selected: false, …}
length
:
5
[[Prototype]] :
Array(0)

2

Answers


  1. Chosen as BEST ANSWER

    I can't loop over dataState, it only takes data. And above I put dataState but that doesn't change anything, I retrieve it in the console but they are not displayed.

    <div class="container">
      <ng-container *ngIf="products$|async as result"[ngSwitch]="result.dataState">
        {{result.dataState}}
        <ng-container *ngSwitchCase="DataStateEnum.LOADING" >
          Loading...
        </ng-container>
        <ng-container *ngSwitchCase="DataStateEnum.ERROR" >
          <div class="alert-danger">
            {{result.errorMessage}}
          </div>
        </ng-container>
        <ng-container *ngSwitchCase="DataStateEnum.LOADED" >
          <table class="table">
            <tr>
              <th>ID</th><th>Name</th><th>price</th><th>quantity</th><th>Selected</th><th>available</th>
            </tr>
            <tr *ngFor="let p of result.data">
              <td>{{p.id}}</td>
              <td>{{p.name}}</td>
              <td>{{p.price}}</td>
              <td>{{p.quantity}}</td>
              <td>{{p.selected}}</td>
              <td>{{p.available}}</td>
              <td>
    

    html component


  2. You might mistake the value for ngSwitch so the data list will never show. It should be result.dataState instead of result.data

    <div class="container">
      <ng-container *ngIf="products$|async as result"[ngSwitch]="result.dataState">
        {{result.dataState}}
        <ng-container *ngSwitchCase="DataStateEnum.LOADING" >
          Loading...
        </ng-container>
        <ng-container *ngSwitchCase="DataStateEnum.ERROR" >
          <div class="alert-danger">
            {{result.errorMessage}}
          </div>
        </ng-container>
        <ng-container *ngSwitchCase="DataStateEnum.LOADED" >
          <table class="table">
            <tr>
              <th>ID</th><th>Name</th><th>price</th><th>quantity</th><th>Selected</th><th>available</th>
            </tr>
            <tr *ngFor="let p of result.data">
              <td>{{p.id}}</td>
              <td>{{p.name}}</td>
              <td>{{p.price}}</td>
              <td>{{p.quantity}}</td>
              <td>{{p.selected}}</td>
              <td>{{p.available}}</td>
              <td>
              <button [ngClass]="p.selected?'btn-success':'btn-danger'" (click)="onSelect(p)">
                <span *ngIf="p.selected">UnSelect</span>
                <span *ngIf="!p.selected">Select</span>
              </button>
              </td>
              <td>
                <button class="btn btn-danger" (click)="onDelete(p)">
                  <span  class="fa fa-trash-o">Delete</span>
                </button>
              </td>
            </tr>
          </table>
        </ng-container>
      </ng-container>
    </div>
    

    Also, in typescript file, there are some spelling mistakes: dataSate

    onGetAllProducts(){
         this.products$ = this.productService.getAllProducts().pipe(
           map(data=>{
             console.log(data);
             return ({ dataState:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
           startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
        catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
      }
    
     // protected readonly json = json;
      onGetSelectedProducts() {
        this.products$ = this.productService.getSelectedProducts().pipe(
          map(data=>{
            console.log(data);
            return ({ dataState:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
          startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
          catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
      }
    
      onGetAvailableProducts() {
        this.products$ = this.productService.getAvailableProducts().pipe(
          map(data=>{
            console.log(data);
            return ({ dataState:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
          startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
          catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
      }
    
      onSearch(dataForm: any) {
        this.products$ = this.productService.searchProducts(dataForm.keyword).pipe(
          map(data=>{
            console.log(data);
            return ({ dataState:DataStateEnum.LOADED, data:data})}),//map recupere liste pdt et retourne message Loaded et les data
          startWith({dataState: DataStateEnum.LOADING}), //startwith affiche pendant le chargement :"loading"
          catchError(err =>of ({dataState: DataStateEnum.ERROR, errorMessage:err.message("erreur de chargement")})))
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search