Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

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

Estou fazendo o curso de Angular, e ao receber as fotos da API, consigo receber tudo ok. Porém, quando vou utlizar uma API aqui de um projeto, dá o seguinte erro:

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

O JSON que eu recebo da API é do seguinte formato:

{
    "objetos": [
        {
            "id": 8,
            "created": "2019-02-25T22:34:09-03:00",
            "modified": "2019-02-25T22:38:39-03:00",
            "chave": "valor"
        },
        {
            "id": 10,
            "created": "2019-02-26T21:02:03-03:00",
            "modified": "2019-02-26T21:02:03-03:00",
            "chave": "valor"
        },

Como posso solucionar? Estou tentando inserir esse valores trazidos da API, no Angular em uma tabela. API que estou utilizando é desenvolvida em CakePHP.

9 respostas

Fala aí Gisiona, tudo bem? Consegue me mandar os códigos (Service, Component, etc..)? Ficaria mais fácil tentar lhe ajudar.

Fico no aguardo.

Oi, boa tarde. Agradeço demais se puder ajudar. Seguem os códigos.

Esse é o meu service

import { Injectable } from '@angular/core';
import { NovaEmpresa } from './nova-empresa';
import { HttpClient, HttpHeaders} from '@angular/common/http';
import { Observable } from 'rxjs';

const API_URL = 'http://localhost:3000/empresas';

const httpOptions = {
    headers: new HttpHeaders({
    'Content-Type':  'application/json',
    })
};

// pois só irei usar para empresa, por isso o root.
@Injectable({ providedIn: 'root' })
export class EmpresarService {

    constructor(private http: HttpClient) { }


    addEmpresa (novaEmpresa: NovaEmpresa): Observable<NovaEmpresa> {

        console.log(novaEmpresa);
        return this.http.post<NovaEmpresa>(API_URL + '/add', novaEmpresa, httpOptions);

    }

    listarEmpresas( ) {
        return this.http
                .get<NovaEmpresa[]>(API_URL + '.json');
    }

}

Meu empresa.component.ts

import { OnInit, Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators,  } from '@angular/forms';
import { EmpresarService } from '../empresa.service';
import { NovaEmpresa } from '../nova-empresa';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-empresa',
  templateUrl: './empresa.component.html',
  styleUrls: ['./empresa.component.css']
})

export class EmpresaComponent implements OnInit {

  formularioEmpresa: FormGroup;
  empresas$: Observable<NovaEmpresa[]>;

  constructor(
                private formBuilder: FormBuilder,
                private empresaService: EmpresarService,
                private rotas: Router
              ) { }

  ngOnInit() {
    this.formularioEmpresa = this.formBuilder.group({
      nome: ['', Validators.required],
      razao_social: ['', Validators.required],
      telefone: ['', Validators.required],
      endereco: ['', Validators.required],
      responsavel: ['', Validators.required],
      email_contato: ['',
            [
            Validators.required,
            Validators.email,
            ]
        ]
    });

    this.listarEmpresas();

  }

  addEmpresa() {

    const novaEmpresa = this.formularioEmpresa.getRawValue() as NovaEmpresa;

    this.empresaService.addEmpresa(novaEmpresa)
        .subscribe
        (
            () => this.rotas.navigate(['']),
            err => console.log(err)
        );

  }

  listarEmpresas() {
    this.empresas$ = this.empresaService.listarEmpresas();
  }


}

Meu html

<tbody>
          <tr *ngFor="let empresa of empresas$">
            <th scope="empresa">
            </th>
            <td>{{empresa.nome}}</td>
            <td>{{empresa.razao_social}}</td>
            <td>
              <i class="far fa-edit fa-2x cyan-text pr-3"></i>
              <i class="far fa-trash-alt fa-2x cyan-text pr-3"></i>
            </td>
          </tr>
 </tbody>

Minha Interface NovaEmpresa

export interface NovaEmpresa {
    id: string;
    nome: string;
    razao_social: string;
    telefone: string;
    endereco: string;
    responsavel: string;
    email_contato: string;
}

O JSON que eu recebo.

{
    "empresas": [
        {
            "id": 1,
            "nome": "teste insert 01",
            "razao_social": "teste razao insert 01",
            "telefone": "(85) 99999-9999",
            "endereco": "Rua H TEste X",
            "responsavel": "teste insert 01",
            "email_contato": "teste@mail.com "
        },
        {
            "id": 2,
            "nome": "T01",
            "razao_social": "R01",
            "telefone": "8599999999",
            "endereco": "E01 e",
            "responsavel": "k01",
            "email_contato": "E@01"
        }
]
}

O erro que dá:

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

Com isso, não estou conseguindo mandar os dados para a tabela, pois apresenta este erro. Vi o problema, porém não consigo resolver. Pq se não tivesse o

{
    "empresas": [
        {
            "id": 1,

e fosse apenas

 [
        {
            "id": 1,
        demais dados do json

eu conseguiria, porém a API retorna o JSON dessa maneira aí. O que quebra é vir o nome empresas e não o array diretamente. E não sei como tratar isso no Angular.

Alguém, pode me dá uma ajuda?

Matheus Castiglioni, você pode me dar uma ajuda?

Fala aí Gisiona, tudo bem? O problema está no seu for, você está tentando iterar um objeto, isso porque sua API retorna um objeto que tem uma propriedade chamada empresas ai dentro das empresas que você faz a interação por ser um array.

Para corrigir, faça o seguinte:

  1. Transforme a propriedade empresas$ em um array:
empresas: [];
  1. Busque os dados e adiciona o valor da propriedade empresa do JSON para a propriedade da classe:
listarEmpresas() {
this.empresaService.listarEmpresas()
    .subscribe(resp => this.empresas = resp.empresas);
}

Espero ter ajudado.

Dá o seguinte erro ao compilar: Type 'Subscription' is not assignable to type 'empresas[]'. Property 'length' is missing in type 'Subscription'.

solução!

Faz o cast de empresas para array, você não deve estar usando interface dai o TypeScript está se perdendo:

listarEmpresas() {
    this.empresaService.listarEmpresas()
        .subscribe(resp => this.empresas = resp.empresas as []);
}

Espero ter ajudado.

Sim. Consegui resolver. Muito obrigado. Só não entendi o "você não deve estar usando interface". Você quis dizer que eu não devo usar interface, ou que eu não estou usando interface? kk. Estou usando interface. É uma boa prática?

Show \o/, fico feliz que tenha conseguido resolver.

Quando eu digo: "você não deve estar usando interface" foi um comentário onde achei que você não estava utilizando.

Eu recomendo utilizar sim, é muito bom para definir os tipos.

Obs: Consegue marcar a dúvida como solucionada? Assim conseguimos ajudar outros alunos com problemas parecidos.

Abraços e bons estudos.