5

Im currently developing the frontend part of a crud application. I was implementing lazy pagination when I got this error

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

I have already looked into planty of questions with the same error, but I didn't find any solutions

Obs: already tried using the pipe | keyvalue, didnt work

Here is a part of the object I'm passing to the pagination = cidades:

[
    {
        "id": 6,
        "nome": "Florianópolis",
        "qtdHabitantes": null,
        "estado": "SC"
    },
    ...
]

Here's the service where i do the request:

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Pageable } from '../pageable';
import { RequestUtil } from '../request-util';
import { Cidade } from './cidade';
import { CidadeFiltro } from './cidadeFiltro';

@Injectable({
  providedIn: 'root'
})
export class CidadeService {

  apiUrl = environment.apiUrl;
  cidadesUrl = environment.slashApi + '/cidades';

  constructor(private http: HttpClient) { }

  listar(filtro: CidadeFiltro, pageable: Pageable): Observable<any>{
    const options = RequestUtil.buildOptions(Object.assign(filtro, pageable));
    return this.http.get<any>(`${this.cidadesUrl}`, options);
  }
  ...

My component.ts:

export class CidadesComponent implements OnInit, OnChanges {

  @ViewChild('grid') grid: any;

  cidades: any[] = [];

  estado = new Estado();

  estados = [];

  estadoSelected:any = '';

  filtro = new CidadeFiltro();
  pageable = new Pageable();

  totalRegistros = 0;

  @BlockUI('lista-cidades') blockUI!: NgBlockUI;

  constructor(private cidadeService:CidadeService, private messageService: MessageService ) { }

  ngOnChanges(changes: SimpleChanges): void {
    this.cidades = this.cidades
  }

  ngOnInit() {
    this.listar();
    this.estados = this.estado.estados;
  }

  listar(pagina:number = 0){
    this.blockUI.start();
    this.filtro.estado = this.estadoSelected.name;
    this.pageable.page = pagina;
    this.cidadeService.listar(this.filtro, this.pageable).pipe(finalize(() => this.blockUI.stop())).subscribe(data => {
      this.totalRegistros = data.totalElements;
      this.cidades = data.content;
    }),
    retry(3),
    catchError(error => {
      console.log('Não foi possível listar as cidades');
      return of(0);
    });
  }

And last my component.html

<div *blockUI="'lista-cidades'">
  <p-table [value]="cidades" #grid
    [lazy]="true" [totalRecords]="registros" (onLazyLoad)="aoMudarPagina($event)"
  [paginator]="true" [rows]="size" responsiveLayout="scroll">

    <ng-template pTemplate="emptymessage">
      <tr><td>Nenhuma cidade encontrada</td></tr>
    </ng-template>

    <ng-template pTemplate="header">
        <tr>
            <th>Nome</th>
            <th>Habitantes</th>
            <th>Estado</th>
            <th>Ações</th>
        </tr>
    </ng-template>

    <ng-template pTemplate="body" let-cidade>
        <tr>
            <td>{{cidade.nome}}</td>
            <td>{{cidade.qtdHabitantes | number}}</td>
            <td>{{cidade.estado}}</td>
            <td class="acoes">
              <button pButton icon="pi pi-pencil" pTooltip="Editar" tooltipPosition="top" [routerLink]="['/cidades', cidade.id]"></button>
              <button pButton class="p-button-danger" icon="pi pi-trash"  pTooltip="Excluir" tooltipPosition="top"
              (click)="deletar(cidade)"></button>
            </td>
        </tr>
    </ng-template>
  </p-table>
</div>

error log:

ERROR Error: NG0900: Error trying to diff '[object Object]'. Only arrays and iterables are allowed
    at DefaultIterableDiffer.diff (core.mjs:27502)
    at NgForOf.ngDoCheck (common.mjs:3170)
    at callHook (core.mjs:2552)
    at callHooks (core.mjs:2511)
    at executeCheckHooks (core.mjs:2443)
    at refreshView (core.mjs:9493)
    at refreshEmbeddedViews (core.mjs:10609)
    at refreshView (core.mjs:9508)
    at refreshComponent (core.mjs:10655)
    at refreshChildComponents (core.mjs:9280)

Can someone help me?

UPDATE I have thinked about implementing this code in the listar() method:

listar(pagina:number = 0){
    this.blockUI.start();
    this.filtro.estado = this.estadoSelected.name;
    this.pageable.page = pagina;
    this.cidadeService.listar(this.filtro, this.pageable).pipe(finalize(() => this.blockUI.stop())).subscribe(data => {
      this.totalRegistros = data.totalElements;
      this.cidades.push(data.content);
      this.cidades = this.cidades[0];
      console.log(this.cidades)
    })

but then i get the error

ERROR TypeError: Cannot read properties of undefined (reading 'push')

And my list becomes empty

15
  • Hello @tabletigr! what's p-table is it a library or another component? I'm thinking that you might be binding the wrong property to a *ngfor or something like Commented Mar 16, 2022 at 13:10
  • Hi @rmjoia, p-table is a component from primeng. And no, im not biding the wrong property to the for loop, its actually supposed to be cidades, but i think im supposed to get the value as an array or something like that Commented Mar 16, 2022 at 13:12
  • put complete error log and what is there in cidades? Commented Mar 16, 2022 at 13:13
  • @tabletigr I saw it was cidades, was just wondering if the component was doing something else. if you could put something on stackblitz or something that people can look at might be easier to help, not sure if it's possible though. Commented Mar 16, 2022 at 13:15
  • 1
    @rmjoia i dont know if i can upload since the frontend part is too big, tried once and didnt work. But i think the code I already shared here is probably enough Commented Mar 16, 2022 at 13:18

4 Answers 4

5

One thing that is popping up to me is that you're using the any type.

Doing something in the service like return this.http.get<Cidades[]> would ensure that the response will be parsed to an array of Cidades and might let you know if something goes wrong there. (I can't remember exactly if it throws if it can't)

Take a look at Requesting a typed response

Also, use cidades: Cidades[] = []; instead, and you might see where the problem is, when something else is assigned.

Avoid as much as possible to use the type any or you'll loose all the type safety and strange things might happen.

For instance, if something else that isn't Cidades[] is assigned to this.cidades the compiler will complain in design time and you can see what's going on.

Since I didn't create a project with your code I don't know exactly what the error is.

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

1 Comment

no prob. I use the any type only on tests where I don't care much about type-safety and even then, only if I can't come up with a type.
0

My code was like this when I had this problem:

public join: IReservation[] |any; 

loadreserve(): void {
    this.reserve.list().subscribe((daya) => {
        this.dispo = daya; 
        for (let ter of this.dispo) {
            let toto : number|any = ter.terrain?.nbrJoueurs; 
            let tat: number|any = ter.nbrjoueur; 
            this.comp = toto - tat;
            if (this.comp >= this.numberofJoin) {
                this.join = ter;
                console.log(this.join);
            }
        }
    });
}

The problem: During my for loop, I returned an object to display it, but I needed an array of objects, so I made this modification:

loadreserve(): void {
    this.join = [];
    this.reserve.list().subscribe((daya) => {
        this.dispo = daya; 
        for (let ter of this.dispo) {
            let toto : number|any = ter.terrain?.nbrJoueurs; 
            let tat: number|any = ter.nbrjoueur; 
            this.comp = toto - tat;
            if (this.comp >= this.numberofJoin) {
                this.join.push(ter);
                console.log(this.join);
            }
        }
    });
}

And it works for me.

Comments

0

I have a .Net Core API with an Angular front-end. My issue was caused by calling an external API which was returning HTTP 500 Internal Server Error. The unhandled error was then showing as an NG0900 in the console. The root cause ended up being that data migrations were not applied to the external API.

Comments

0

My problem is that my API returned an object that contained an array:

  {
  "$id": "1",
  "$values": [
    {
      "$id": "2",
      "id": 5,
      "name": "stringskdlasdkjsjdkasjdljsakdljsad",
      "imageUrl": "skajddjkasdkjldajkdajkadsjkdsaj",
      "description": "stringsdasdksadlskda;lsdksaldka;sldkas;ldkasl;dk;sldkal;dkas;ldkals;kd;asld",
      "creationDate": "2024-04-19T14:55:48.415",
      "writtenBy": "string",
      "content": "string",
      "commentsCount": 0,
      "comments": null,
      "likesAmount": 0,
      "creationDateFormatted": null
    },

In which case I needed to adjust my observer to extract the values:

   this.blogsObserver = {
      next:(response) => {
        // @ts-ignore
        this.blogsArray= response["$values"]
      },
      error:(error) => {
        console.error('Error loading blogs',error)
      },
      complete:() => {
        console.log('Loaded blogs from the API.')
      }
    }
  }

Comments

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.