Reputation: 61
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
Upvotes: 4
Views: 41655
Reputation: 51
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.')
}
}
}
Upvotes: 0
Reputation: 429
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.
Upvotes: 0
Reputation: 1
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.
Upvotes: 0
Reputation: 980
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.
Upvotes: 4