我想在 Angular V.17 html 组件中显示以 JSON 格式检索的数据。但是,即使我将它们放在控制台中,它也不会显示在我的表中。我不明白。 事实上,当我到达产品页面时,我应该调用“onGetAllProducts()”方法,该方法调用服务及其 getAllProducts() 方法。鉴于我的 json 数据库 (db.json) 中有 5 个产品,因此符合条件并且应显示数据。我在控制台中检索它们,但不在 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
}
]
}
控制台视图: (5) [{…}, {…}, {…}, {…}, {…}] 0 : {id: 1, 名称: '计算机', 价格: 4300, 数量: 600, 选择: true, …} 1 : {id:2,名称:'打印机',价格:300,数量:100,选择:true,...} 2 : {id:3,名称:'智能手机',价格:1200,数量:200,选择:true,...} 3 : {id: 4, 名称: 'juin', 价格: 2000, 数量: 500, 选择: false, …} 4 : {id: 5,名称:'souris',价格:50,数量:200,选择:false,...} 长度 : 5 [[原型]] : 数组(0)
您可能会误认为 ngSwitch 的值,它应该是
result.dataState
而不是 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>
此外,在打字稿文件中,存在一些拼写错误: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")})))
}