首页 > 解决方案 > Angular 8 - HttpClient 获取一个复杂的 JSON 对象并填充一个 html 表

问题描述

我正在使用 Angular 8,并且正在查询端点以获取对象。当我通过高级 REST 客户端调用它时,我得到以下返回的 JSON:

得到:http://localhost:8090/curso_conductor/

回报:

{
  "dato": [{
      "ID_CURSO_CONDUCTOR": 1,
      "F_INICIO": "2019-09-19T05:00:00.000+0000",
      "F_FIN": "2019-12-20T05:00:00.000+0000",
      "ESTADO": "1",
      "CARNET_C": "l584f",
      "F_CADUCIDAD": "2022-06-20T05:00:00.000+0000",
      "F_EMISION": "2017-06-20T05:00:00.000+0000",
      "ID_CURSO": 1,
      "ID_PERSONA": 3
    },
    {
      "ID_CURSO_CONDUCTOR": 2,
      "F_INICIO": "2019-08-20T05:00:00.000+0000",
      "F_FIN": "2019-12-20T05:00:00.000+0000",
      "ESTADO": "1",
      "CARNET_C": "8574h",
      "F_CADUCIDAD": "2023-04-05T05:00:00.000+0000",
      "F_EMISION": "2017-04-08T05:00:00.000+0000",
      "ID_CURSO": 1,
      "ID_PERSONA": 5
    },
    {
      "ID_CURSO_CONDUCTOR": 3,
      "F_INICIO": "2019-10-09T05:00:00.000+0000",
      "F_FIN": "2019-12-10T05:00:00.000+0000",
      "ESTADO": "1",
      "CARNET_C": "2685f",
      "F_CADUCIDAD": "2022-08-10T05:00:00.000+0000",
      "F_EMISION": "2017-08-09T05:00:00.000+0000",
      "ID_CURSO": 1,
      "ID_PERSONA": 6
    }
  ],
}

在 Angular 8 中,我有一个服务,我想在其中对将返回上述 JSON 的端点进行 http 调用。

getCursoConductor(): Observable<Curso_Conductor[]>{
  return this.http.get<Curso_Conductor[]>(this.curso_conductores).pipe();
}

如您所见,需要将结果放入Curso_Conductor对象中。

我的模型是这样的:

export class Curso_Conductor {
    dato: Dato[];
}

export class Dato {
    ID_CURSO_CONDUCTOR: number;
    F_INICIO:           string;
    F_FIN:              string;
    ESTADO:             string;
    CARNET_C:           string;
    F_CADUCIDAD:        string;
    F_EMISION:          string;
    ID_CURSO:           number;
    ID_PERSONA:         number;
}

我的问题是如何将数据放入Curso_conductorComponent.html

这是我的component.html

<table class="table table-hover">
  <thead>
    <tr>
      <th>ID</th>
      <th>FECHA INICIO</th>
      <th>FECHA FIN</th>
      <th>ESTADO</th>
      <th>Nro CARNET</th>
      <th>FECHA CADUCIDAD</th>
      <th>FECHA EMISION</th>
      <th>IDCURSO</th>
      <th>IDPERSONA</th>
      <th colspan="2">OPCION</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngIf="curso_conductoresObservable | async as curso_conductores else empty">
      <tr *ngFor="let curso_conductor of curso_conductores">
        <td>{{curso_conductor.id_curso_conductor}}</td>
        <td>{{curso_conductor.f_inicio}}</td>
        <td>{{curso_conductor.f_fin}}</td>
        <td>{{curso_conductor.estado}}</td>
        <td>{{curso_conductor.carnet_c}}</td>
        <td>{{curso_conductor.f_caducidad}}</td>
        <td>{{curso_conductor.f_emision}}</td>
        <td>{{curso_conductor.id_curso}}</td>
        <td>{{curso_conductor.id_persona}}</td>
        <td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
        <td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
      </tr>
  </tbody>
</table>

我的component.ts

  curso_conductores: Curso_Conductor[];
  constructor(private service: ServiceService, private router: Router) { }
  @Input() nombre = '';

  ngOnInit() {
    this.service.getCursoConductor()
      .subscribe(data => {this.curso_conductores=data });
  }

我收到此错误:

找不到“object”类型的不同支持对象“[object Object]”。NgFor 仅支持绑定到 Iterables,例如 Arrays。

标签: jsonangularhttpclient

解决方案


您的实施存在一些问题。

  1. 您从 API 获得的数组存在于dato属性中。理想情况下,您应该为此创建一个界面:

    export interface ApiResponse {
      dato: Curso_Conductor[];
    }
    
    export interface Curso_Conductor {
      ID_CURSO_CONDUCTOR: number;
      F_INICIO: string;
      F_FIN: string;
      ESTADO: string;
      CARNET_C: string;
      F_CADUCIDAD: string;
      F_EMISION: string;
      ID_CURSO: number;
      ID_PERSONA: number;
    }
    
  2. 然后,您必须更新您的服务以反映您期望的数据类型。我也在更改服务的名称,因为ServiceService这根本没有意义:

    import { Injectable } from "@angular/core";
    import { HttpClient } from "@angular/common/http";
    import { Observable } from "rxjs";
    
    import { ApiResponse } from "./models/conductor.model";
    
    @Injectable()
    export class DataService {
      curso_conductores = "assets/data.json";
    
      constructor(private http: HttpClient) {}
    
      getCursoConductor(): Observable<ApiResponse> {
        return this.http.get<ApiResponse>(this.curso_conductores);
      }
    }
    
  3. 你在你subscribeObservable组件中,你也在使用async管道。它会自动为您解包。所以只要坚持使用async模板中的管道。这也是推荐的方式:

    import { Component } from "@angular/core";
    import { Curso_Conductor, ApiResponse } from "./models/conductors.model";
    import { DataService } from "./data.service";
    import { Observable } from "rxjs";
    import { map } from "rxjs/operators";
    
    @Component({
      selector: "my-app",
      templateUrl: "./app.component.html",
      styleUrls: ["./app.component.css"]
    })
    export class AppComponent {
      curso_conductores$: Observable<Array<Curso_Conductor>>;
    
      constructor(private service: DataService) {}
    
      ngOnInit() {
        this.curso_conductores$ = this.service.getCursoConductor()
          .pipe(
            map((apiResponse: ApiResponse) => apiResponse.dato)
          );
      }
    }
    
  4. 最后,对象字段都是大写的,但您在模板中将它们用作小写。这也需要修复:


<table class="table table-hover" border="1">
    <thead>
        <tr>
            <th>ID</th>
            <th>FECHA INICIO</th>
            <th>FECHA FIN</th>
            <th>ESTADO</th>
            <th>Nro CARNET</th>
            <th>FECHA CADUCIDAD</th>
            <th>FECHA EMISION</th>
            <th>IDCURSO</th>
            <th>IDPERSONA</th>
            <th colspan="2">OPCION</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let curso_conductor of (curso_conductores$ | async) as curso_conductores">
            <td>{{curso_conductor.ID_CURSO_CONDUCTOR}}</td>
            <td>{{curso_conductor.F_INICIO}}</td>
            <td>{{curso_conductor.F_FIN}}</td>
            <td>{{curso_conductor.ESTADO}}</td>
            <td>{{curso_conductor.CARNET_C}}</td>
            <td>{{curso_conductor.F_CADUCIDAD}}</td>
            <td>{{curso_conductor.F_EMISION}}</td>
            <td>{{curso_conductor.ID_CURSO}}</td>
            <td>{{curso_conductor.ID_PERSONA}}</td>
            <td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
            <td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
        </tr>
    </tbody>
</table>

希望这可以为您解决这个问题。


这是您参考的工作示例 StackBlitz


推荐阅读