Search code examples
arraysangulartypescriptundefinedsubscribe

Angular return me an Array as undefined, but I had defined previously


I'm trying to use Google Books API. Firstly I created the interfaces that worked properly, then I created a method which return me an Array with a list of Books.


    public getBooks(): Observable<Book[]>{
        return this.http.get<Book[]>('https://www.googleapis.com/books/v1/volumes?q=filibusterismo');
    
      }

(I had added the element which I want to search, "filibusterismo", in order to avoid mistakes, but I would change later.)

Then, I want to use the Array of Book, but I can not use a ngFor loop because getBook return me an observable Array of Books instead of an Array of Books. This was my original constructor


   books:Book[];
     constructor(private GoodreadsService:GoodreadsService) { }
   
     ngOnInit() {
      this.libro=this.GoodreadsService.getBooks();
   }

I had tried to fix this using async.

*ngFor="let book of books | async"

But I have the same problem. So reading post in SO I learnt that I have to use subscribe in the ngOnInit(), like this.


     this.GoodreadsService.getBooks().subscribe(res=>{this.books=res},
          error => { // on failure
            console.log('Error Occurred:');
          });

The problem, is that whereas I does not return me any kind of error, if I write

console.log(this.libro1);

The console say that the array is undefined, whereas I had defined it as an array of Book. Furthermore, I still can not use an ngFor.

I also had tried to map the getBook method, in order that return me an Array instead of an observable array, but I could not do it in spite of reading a lot of question in SO.

So, would somebody tell me how can I fix this issue, in order I could use an ngFor in the HTML?

My HTML is this


    <p>busqueda works!ss </p>
    <table>
      <thead>
          <th>Name</th>
          <th>Indexs</th>
      </thead>
      <tbody>
        <div *ngFor="let book of books | async">
            <h1  >
                <p>prueba</p>
            </h1>
          </div>
      </tbody>
    </table>


Solution

  • Here's how you need to do it. Initialize the API call and subscribe to accordingly in order to send the request. After the response is returned then iterate over the items over it.

    Please refer to the working sample stackblitz attached here.

    Sample component.ts :

    import { Component, OnInit } from "@angular/core";
    import { SampleService } from "./sample.service";
    
    @Component({
      selector: "my-app",
      templateUrl: "./app.component.html",
      styleUrls: ["./app.component.css"]
    })
    export class AppComponent implements OnInit {
      books: any;
      constructor(public sample: SampleService) {}
      ngOnInit() {
        this.sample.getBooks().subscribe(data => {
          console.log(data.items)
          this.books = data.items;
        });
      }
    }
    

    Sample HTML :

    <table>
        <thead>
        </thead>
        <tbody>
            <div *ngFor="let book of books">
                <h4>
                    <p>kind : {{book.kind}}</p>
            <p>Id : {{book.id}}</p>
            <p>etag : {{book.etag}}</p>
                </h4>
            </div>
        </tbody>
    </table>