0
votes

I'm trying to display JSON response but I get this error: core.js:6185 ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed.

Error Img

How can I solve this issue? How can I convere it to array ?

TS

export interface Book {
  id: number,
  book_name: string,
  book_issue: Date,

}

Service.ts

export class BookApiService {
  private bookUrl  = "http://127.0.0.1:5000/books"
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }
    constructor (private http: HttpClient){}

    getBook(): Observable<Book[]> {
      return this.http.get<Book[]>(this.bookUrl ,this.httpOptions)
      .pipe(
        catchError(this.errorHandler)
      )
      }
  
  errorHandler(error) {
    let errorMessage = '';
    if(error.error instanceof ErrorEvent) {
      errorMessage = error.error.message;
    } else {
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    return throwError(errorMessage);
 }

template

<ul *ngFor="let book of books">
    <li>{{book.book_name}}</li>
</ul>

Component

export class AppComponent implements OnInit {
  title = 'app';
  books: Book[] = [];

  constructor(public rs : BookApiService){}

  ngOnInit(): void {
    this.rs.getBook().subscribe((data: Book[])=>{
      this.books = data;
      console.log(this.books);
    })  
  }

Backend API Response:

{"books":[{"book_issue":"Fri, 13 Mar 2020","book_name":"Book1","id":1},
{"book_issue":"Fri, 13 Mar","book_name":"Book2",                                                                                                                                                                                                "id":2}],
"success":true}                                                                                                                                                                                           

and this is the console log: console Log

3
*ngFor="let book of books.books"..? - MikeOne

3 Answers

1
votes

Update your code as below :

<ul *ngFor="let book of books?.books">
    <li>{{book.book_name}}</li>
</ul>

The response returned from your API is an object and you are assigning it to the variable used in ngFor , which expects an array. so its throwing error.

Another way to solve this would be to assign your variable as below :

this.rs.getBook().subscribe((data: any)=>{
      this.books = data.books;
      console.log(this.books);
    }) 

and then in your html use this as below :

<ul *ngFor="let book of books">
    <li>{{book.book_name}}</li>
</ul>
1
votes

try doing

getBooks(): Observable<Book []> {
  return this.http.get<{books: Book[]}>(this.bookUrl, this.httpOptions)
           .pipe(
              map(response => response.books)
            )
}
     
0
votes

You said the following is the Response:

{"books":[{"book_issue":"Fri, 13 Mar 2020","book_name":"Book1","id":1},
{"book_issue":"Fri, 13 Mar","book_name":"Book2",                                                                                                                                                                                                "id":2}],
"success":true}

that is wrong since the object you get is not a array of books.

It is a JSON Object with the Key books that contains a Array of books.

If this is the case:

EDIT you do can do this, since the response does not give you an array in the body:

this.rs.getBook().subscribe((data: object)=>{
      this.books = data['books'];
      console.log(this.books);
    })  

or you could define a wrapper class:

export class BookResponse{
 books: Book[];
 success: boolean;
}

    getBook(): Observable<Book[]> {
      return this.http.get<BookResponse>(this.bookUrl ,this.httpOptions)
      .pipe(
        catchError(this.errorHandler)
      ).pipe(map(body => body.books))
      }

this.rs.getBook().subscribe((data: Book[])=>{
      this.books = data;
      console.log(this.books);
    })