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
}
]
}
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
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.
You might mistake the value for ngSwitch so the data list will never show. It should be
result.dataState
instead ofresult.data
Also, in typescript file, there are some spelling mistakes:
dataSate