'Angular 12 Observable<Object[]> Error when trying to perform a get method
I have been trying to make some sense of this error I'm getting on Angular 12.
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
This is my service:
import { HttpClient } from '@angular/common/http';
import { Catalogo } from './../Models/Catalogo';
import { Observable } from 'rxjs';
const baseUrl = 'http://localhost:8080/'
@Injectable ({
providedIn: 'root'
})
export class CatalogoService {
constructor(private http: HttpClient) { }
getAll(): Observable<Catalogo[]> {
console.log(this.http.get<Catalogo[]>(baseUrl));
return this.http.get<Catalogo[]>(baseUrl);
}
And this is my component:
import { Router } from '@angular/router';
import { CatalogoService } from './../../Services/catalogo.service';
import { Catalogo } from "./../../Models/Catalogo";
import { FormGroup, FormBuilder } from '@angular/forms';
@Component({
selector: 'app-catalogo',
templateUrl: './catalogo.component.html',
styleUrls: ['./catalogo.component.scss']
})
export class CatalogoComponent implements OnInit {
catalogo?: Catalogo[];
currentCatalogo: Catalogo = {};
currentIndex = -1;
constructor(private catalogoService: CatalogoService) { }
ngOnInit(): void {
this.retrieveCatalogo();
}
retrieveCatalogo(): void {
this.catalogoService.getAll()
.subscribe(
data => {
this.catalogo = data;
console.log(data);
},
error => {
console.log(error);
});
}
Edit: Here's the HTML part
<div class="containter">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Modelo</th>
<th scope="col">Precio</th>
<th scope="col">Especificacion</th>
<th scope="col">Imagen</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let catalogo of catalogo; let i = index">
<th scope="row">{{catalogo.id}}</th>
<td>{{catalogo.modelo}}</td>
<td>{{catalogo.precio}}</td>
<td>{{catalogo.especificacion}}</td>
<td>{{catalogo.imagen}}</td>
</tr>
</tbody>
</table>
</div>
I was following a tutorial on how to use serializable with MEAN stack:
https://www.bezkoder.com/angular-12-node-js-express-mysql/ https://www.bezkoder.com/angular-12-crud-app/
but when I try load the page I get the error I mentioned.
My questions are:
Why this is happening? (I'm kind of new to angular)
is this how you are supposed to return an array with Observables? "this.http.get<Catalogo[]>(baseUrl);"
EDIT: This is the output for the method on the service class:
Observable
operator: MapOperator {thisArg: undefined, project: ƒ}
source: Observable
operator: FilterOperator
predicate: (event) => event instanceof HttpResponse
thisArg: undefined
[[Prototype]]: Object
call: ƒ call(subscriber, source)
constructor: class FilterOperator
[[Prototype]]: Object
source: Observable
operator: MergeMapOperator {concurrent: 1, project: ƒ}
source: Observable {_isScalar: false, _subscribe: ƒ}
_isScalar: false
[[Prototype]]: Object
_isScalar: false
[[Prototype]]: Object
_isScalar: false
[[Prototype]]: Object
Edit: the output from the subscribe method
Subscriber {closed: false, _parentOrParents: null, _subscriptions: Array(1), syncErrorValue: null, syncErrorThrown: false, …}
closed: true
destination: SafeSubscriber
closed: true
destination: {closed: true, next: ƒ, error: ƒ, complete: ƒ}
isStopped: true
syncErrorThrowable: false
syncErrorThrown: false
syncErrorValue: null
_complete: undefined
_context: null
_error: error => { console.log(error); }
_next: data => {…}
_parentOrParents: null
_parentSubscriber: null
_subscriptions: null
[[Prototype]]: Subscriber
isStopped: true
syncErrorThrowable: true
syncErrorThrown: false
syncErrorValue: null
_parentOrParents: null
_subscriptions: null
[[Prototype]]: Subscription
complete: ƒ complete()
constructor: class Subscriber
error: ƒ error(err)
next: ƒ next(value)
unsubscribe: ƒ unsubscribe()
_complete: ƒ _complete()
_error: ƒ _error(err)
_next: ƒ _next(value)
_unsubscribeAndRecycle: ƒ _unsubscribeAndRecycle()
Symbol(rxSubscriber): ƒ [_internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_2__.rxSubscriber]()
[[Prototype]]: Object
Thank you!
Solution 1:[1]
Let's simplify the things to make it easier. In order to simplify and increase performance I recommend you using the async pipe. Let me show you.
First in your component.ts you don't need a retrieveCatalogo method, we will store the observable and use it directly in the template with the async pipe.
The component:
import { Router } from '@angular/router';
import { CatalogoService } from './../../Services/catalogo.service';
import { Catalogo } from "./../../Models/Catalogo";
import { FormGroup, FormBuilder } from '@angular/forms';
@Component({
selector: 'app-catalogo',
templateUrl: './catalogo.component.html',
styleUrls: ['./catalogo.component.scss']
})
export class CatalogoComponent implements OnInit {
// We use the $ at the end of the var name as a naming convention for storing observables and subscriptions.
catalogos$!: Observable<Catalogo[]>;
currentCatalogo: Catalogo = {};
currentIndex = -1;
constructor(private catalogoService: CatalogoService) { }
ngOnInit(): void {
// We call the service and store the observable
this.catalogos$ = this.catalogoService.getAll();
}
Now in your component template we need to use the async pipe
...
<tbody *ngIf="catalogos$ | async as catalogos">
<tr *ngFor="let catalogo of catalogos">
<th scope="row">{{catalogo.id}}</th>
<td>{{catalogo.modelo}}</td>
<td>{{catalogo.precio}}</td>
<td>{{catalogo.especificacion}}</td>
<td>{{catalogo.imagen}}</td>
</tr>
</tbody>
...
The async pipe will unsubscribe automatically https://angular.io/api/common/AsyncPipe
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Osakr |
