'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