angulartypescriptobservableasync-pipe

Angular Async Pipe - Array in Object in Observable


I am trying to Learn Async Pipe and how to use them. however I have an issue with using Async Pipe in the following case;

I am using this fake/dummy API Cat API I can't figure how to retrieve the Object Data inside the observable value.

TS Code

import { Component, OnInit } from '@angular/core';
import { HttpService } from '../services/http/http.service';
import { facts } from '../interfaces/facts';
import { Observable } from 'rxjs';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit{
  facts$! : Observable<facts[]>
  constructor(private client : HttpService){

  }
  ngOnInit(): void {

    this.facts$ = this.client.getListFacts(25, 5)
  }

}

Interface

export interface facts {
  fact : string,
  length : number
}

HTML

<div class='home'>
  <ul style="margin: 0 0 0 0">
    <li *ngFor="let fact of (facts$ | async)">{{fact.fact}}</li>
  </ul>
</div>

HTTP Service

  getListFacts(length : number, limit : number) : Observable<facts[]>{
    return this.client.get<facts[]>(`https://catfact.ninja/facts?max_length=${length}&limit=${limit}`)

I have tried to async pipe results, fact of facts list inside the HTML code, however it renders nothing


Solution

  • Your typing of the API response is wrong. What comes from the API is an object with several properties related to pagination, and data array, which is what you're after. One way to consume it would be

    getListFacts(length: number, limit: number) : Observable<facts[]> {
        return this.client
            .get<{ data: facts[] }>(`https://catfact.ninja/factsmax_length=${length}&limit=${limit}`)
            .pipe(map(({ data }) => data));
    }
    

    (Also, the interface should be named Fact, not facts: singular, because it represents a single entry, and uppercase, because that's the convention for types/interfaces/classes).