Angular 4 Observable service not working for an api http get

1.4k views Asked by At

Angular 4 Observable service not working for an api http get.

The http that returns an observable doesnt seem to work.

I'm using the new HttpClient

This is the error I get:

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

Solution?

It doesn't seem to like Observable going to the ngFor. Maybe I need to do a switchMap? in the component.

This is my http service call:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/retry';

import { User } from "../models/user.model";

@Injectable()

export class UserService {
    private baseUrl = "http://jsonplaceholder.typicode.com/users";

    constructor(private http: HttpClient) {
    }

    getUsers(): Observable<User[]> {        
        return this.http.get<User[]>(this.baseUrl)
          .retry(2)
          .catch(e => this.handleError("Get Users Error", e));
    }

    private handleError(errorMessage: string, error: Object): any {
      console.log(errorMessage, error);
    }
};

This is my html:

<div class="column" *ngFor="let user of listOfUsers | async; let i = index">
    <p>{{i + 1}}.{{user.name}}</p>
</div>

This is my component:

import { Component, OnInit } from "@angular/core";
import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/do';

import { UserService } from "../../services/user.service";
import { User } from "../../models/user.model";

@Component({
  selector: "home-users",
  templateUrl: "./home.component.html"
})

export class HomeComponent implements OnInit {
  private listOfUsers: Observable<User[]>;
  loading: boolean;

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.getUsers();
  }

  getUsers(): void {
    this.loading = true;
    this.listOfUsers = this.userService.getUsers().do(_ => this.loading = false);
  }
}

This is my model:

export class User {
  name: string;
};
2

There are 2 answers

3
P. Moloney On

Surely if you change your Home Component to the following it will resolve you issue?

getUsers(): void {
    this.loading = true;
    this.userService.getUsers().subscribe((users) => {
            // --> Observable<T> returns here
            this.listOfUsers = users; // or if json: this.listOfUsers = users.json();
        },
        (errors) => {
            // --> Errors are returned here
        },
        () => {
            // --> always called when finished
            this.loading = false;
        });
}

edit

You'll have to map the returned data for async:

this.listOfUsers = this.userService.getUsers().map((data)=> return data.json() || []);

this.works fine on my side, check out this article: angular-2-async-pipe-example

9
Jota.Toledo On

Do the following changes:

export interface User {
  name: string;
};

@Injectable()

export class UserService {
    private baseUrl = "http://jsonplaceholder.typicode.com/users";

    constructor(private http: HttpClient) {
    }

    getUsers(): Observable<User[]> {
        return this.http.get<User[]>(this.baseUrl)
      .retry(2)
      .catch(e => this.handleError("Get Users Error", e));
}

private handleError(errorMessage: string, error: HttpErrorResponse | any){
  console.log(errorMessage, error);
}

}

The new HttpClient doesnt define a Response class with a json method. Instead of that now developers can use the HTTP methods with a type parameter.

This is the screen shot of my console error:

enter image description here