Consuming an API with Angular

Asked

Viewed 4,910 times

1

I’m trying to consume an API with Angular 5 but it returns me this error:

" Error trying to diff '[object Object]'. Only arrays and iterables are allowed
    at DefaultIterableDiffer.diff".

Response from the API :

    {
    "alunos": [
        {
            "aluno": {
                "id": 655,
                "nome": "Gustavo Henrique",
                "status": "Ativo"
            },
            "mensalidade": {
                "status": "Pago"
            }
        },
        {
            "aluno": {
                "id": 656,
                "nome": "Vivien Jacobs",
                "status": "Ativo"
            },
            "mensalidade": {
                "status": "Débito"
            }
        }
     ]
}

My service:

import { IStudent } from './../students';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { HttpErrorResponse } from '@angular/common/http/src/response';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';


@Injectable()
export class StudentsService {

  public alunos = [];

  // LIST STUDENTS URL
  public list_students_url = 'http://localhost:8000/api/aluno/list';

  constructor(private http: HttpClient) { }


  // Pega todos os alunos.
  getAlunos(): Observable<IStudent[]>
  {
      return this.http.get<IStudent[]>(this.list_students_url)
                      .catch(this.errorHandler);
  }




  errorHandler(error: HttpErrorResponse)
  {
      return Observable.throw(error.message || "Server error");
  }

}

My interface:

export interface IStudent {
alunos: {
    aluno: {
        id: number,
        nome: string,
        status: string,
    },
    mensalidade: {
        status: string
    }
  }
}

My Component:

import { StudentsService } from './services/students.service';
import { Component, OnInit, Input } from '@angular/core';
import { IStudent } from './students';

@Component({
  selector: 'app-students',
  templateUrl: './students.component.html',
  styleUrls: ['./students.component.css']
})
export class StudentsComponent implements OnInit {

  public students = [];
  public errorMsg;
  constructor(private service: StudentsService) { }

  ngOnInit() {

      this.service.getAlunos()
      .subscribe( data => this.students = data,
                 error => this.errorMsg = error);


                 //console.log(this.students);
  }

}
  • To community gives the option to put codes in the body of the question, if you can do the favour of edit and put, just paste the code, select and hit the shortcut CTRL+K that will format the same..

  • Got it, corrected =)

  • 1

    Your interface is incorrect, you are not declaring the array that is in the JSON body

3 answers

0

The problem is that you are not receiving an array but an object that contains an array.

export interface GetAlunosResponse {
     alunos: Estudante[];
}

export interface Estudante: {
      aluno:Aluno;
      mensalidade:Mensalidade;
}

export interface Aluno: {
     id: number,
     nome: string,
     status: string,
}  

export interface Mensalidade: {
     status: string
}

In service:

 getAlunos(): Observable<GetAlunosResponse[]>
  {
      return this.http.get<GetAlunosResponse[]>(this.list_students_url)
                      .catch(this.errorHandler);
  }

0

Make the following change in the method getAlunos()

 getAlunos(): Observable<IStudent[]> {
   return this.http.get<IStudent[]>(this.list_students_url).pipe(
   tap(data => JSON.stringify(data))),
   catchError(this.errorHandler)
 );
}

-2

Its structure is wrong in a general. First to map the returned Json objects it is necessary to create a class, not an interface. I don’t understand very well what you intend to do, but in the case as an example, you would have to create a Student class:

export class Aluno {
    id: number;
    nome: string;
    status: string;
    mensalidade: string;
}

Correct answer from API:

{
    "id": 655,
    "nome": "Gustavo Henrique",
    "status": "Ativo",
    "mensalidade": "Pago"
},
{
    "id": 656,
    "nome": "Vivien Jacobs",
    "status": "Ativo"
    "mensalidade": "Débito"
}

Your method getAlunos

getAlunos(): Observable<Aluno[]>
  {
    return this.http.get(this.list_students_url).pipe(
          map((res: Response) => {
              return res.json();
      }),
      catchError(this.handleError),);
  }
  • Interfaces are more recommended than classes to map Apis because they generate less code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.