1

I am using Angular 8, and am querying an endpoint to get an object. When I call it via Advanced REST Client, I get the following returned JSON:

GET: http://localhost:8090/curso_conductor/

Returns:

{
  "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
    }
  ],
}

In Angular 8, I then have a service, where I want to make an http call to to the endpoint that will return the above JSON.

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

As you can see the result needs to be put into the Curso_Conductor object.

And my model is this:

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;
}

My question is how do I put the data into the Curso_conductorComponent.html?

This is my 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>

And my 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 });
  }

I'm getting this error:

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

2
  • Is that really the full response that you've shown? Your code looks fine to me, but the response object is a bit suspicious. Why is there a ,} after the final bracket closing the array? Makes me suspicious that you're getting an object not an array. Also your English is absolutely fine, nobody would think otherwise. However if you feel inclined there is a completely Spanish speaking StackOverflow at https://es.stackoverflow.com/. Commented Oct 27, 2019 at 23:28
  • Yes, I'm getting an object from back-end, let me explain it. The back-end(java btw) is using a procedure that returns a cursor from the database with a select * from curso_conductor. Usually i used to do all this stuff without the cursor, just the select * from (way more easy front-end), but now I'm trying this and idk how to read the nested json. I'm a software engineer student and new in Angular. Thanks Commented Oct 28, 2019 at 0:03

2 Answers 2

1

There are a few issue with your implementation.

  1. The array that you get from the API is present on the dato property. You ideally you should be creating an interface for that:

    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. You'll then have to update your service to reflect the type of data that you're expecting. I'm also changing the name of the service as ServiceService makes no sense at all:

    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. You're subscribeing to the Observable in your Component and you're also using an async pipe. Which automatically does the unwrapping for you. So just stick to using the async pipe in the template. That's also what's the recommended way:

    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. Finally, the Object fields are all in upper case but you're using them as lower case in the template. That needs to be fixed as well:


<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>

Hope this clears this up for you.


Here's a Working Sample StackBlitz for your ref.

Sign up to request clarification or add additional context in comments.

Comments

0

Are you sure the return type is Curso_Conductor[]? It seems like Curso_Conductor. Try this,

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

...

curso_conductore: Curso_Conductor;
constructor(private service: ServiceService, private router: Router) { }
@Input() nombre = '';
ngOnInit() {
  this.service.getCursoConductor().subscribe(data => {this.curso_conductore=data });
}

and in html

...
<tr *ngFor="let d of curso_conductore.dato.dato">
      <td>{{d.id_curso_conductor}}</td>
      <td>{{d.f_inicio}}</td>
...

6 Comments

I've changed what you mentioned above but I'm getting this error Cannot read property 'dato' of undefined at Object.eval [as updateDirectives] at the line <tr *ngFor="let d of curso_conductores.dato">
can you post a complete sample of returned json?
The complete json is above, only missing a { at the beginning
Not sure exactly the result and its type, add console.log(data) in subscribe and have a look.
{dato: Array(3)} dato: Array(3) 0: {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", …} 1: {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", …} 2: {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", …} length: 3 __proto__: Array(0) __proto__: Object
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.