Marcio
Marcio

Reputation: 1733

Angular - how to get result of a JSON object?

I am trying to use the new Public API V2 CoinMarketCap, but I am trying some difficulty with this.

JSON:

https://api.coinmarketcap.com/v2/ticker/?limit=10

my model Coin:

export class Coins {
    id: string;
    name: string;
    symbol: string;
    rank: number;
    price_usd: number;
    price_btc: number;
    _24h_volume_usd: number;
    market_cap_usd: number;
    available_supply: number;
    total_supply: number;
    percent_change_1h: number;
    percent_change_24h: number;
    percent_change_7d: number;
    last_updated: number;
}

my service:

urlBase = 'https://api.coinmarketcap.com/v2/ticker/?limit=10';
getCoins() {
   return Observable
   .timer(0, 5000)
   .flatMap(() =>  this.http.get(this.urlBase))
   .pipe(
      map(res => res), 
      catchError(this.handleError)
    )
}

my component:

coins: Coins[];
getCoins() {
  this.coinsService.getCoins().subscribe(
    data => {
      this.coins = data;
    });
}

my html:

<div class="card card-inverse" *ngFor="let coin of coins">

output:

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

any suggestion?

thank you

Upvotes: 1

Views: 13368

Answers (5)

Mikinj Mistry
Mikinj Mistry

Reputation: 586

You got this error only because you are iterating an object. You need array of objects to iterate over.

Try below code in your mycomponent file.

getCoins() {
this.coinsService.getCoins().subscribe(
    data => {
        let coins = [];
        for (let key in data) {
            coins.push(data['key']);
        }
      this.coins = coins;
    });
}

Upvotes: 1

Amit Chigadani
Amit Chigadani

Reputation: 29715

From the api data that you are showing, I see that you are assigning this.coins with the object but not an array. You should first convert it into an array and then assign it to this.coins.

getCoins() {
  this.coinsService.getCoins().subscribe(
    data => {
      this.coins = [];
      for(let key in data){
          this.coins.push(data[key]);
       }
    });
}

Or else you could also do this way to convert object to array.

getCoins() {
      this.coinsService.getCoins().subscribe(
        data => {
          this.coins = [];
          Object.keys(data).map((key)=>{ this.coins.push(data[key]) });
        });
}

In your service file

getCoins() {
    return this.http.get(this.urlBase).pipe(map(res => res = res.json()['data']))
}

Working DEMO

Upvotes: 2

Megaklis Vasilakis
Megaklis Vasilakis

Reputation: 31

Ok i tried your example and i see some problems with it. Not sure what you're trying to achieve with timer so ill keep it simple. The response im getting is this: { data: [], metadata: [] }

So i assume that in your map you need to map like this map(res => res.data) to display the data property for example

I rewrote a simple example:

  getCoins() {
    const urlBase = "https://api.coinmarketcap.com/v2/ticker/?limit=10";
    this.http
      .get(urlBase)
      .pipe(map(res => res))
      .subscribe(res => console.log(res));
  }

To get the data property change the above map to .pipe(map(res => res.data))

To avoid ts error you can also type it: .pipe(map((res: { data: any; metadata: any }) => res.data))

You will also need some aditional mapping for the data to match your Coin interface

I can help more if you cant find a way to do it ;)

Upvotes: 2

Lia
Lia

Reputation: 11982

in service:

getCoins(): Observable<any> {
  const api = 'https://api.coinmarketcap.com/v2/ticker/?limit=10';
  return this.httpClient.get(api);    
}

in your component:

getCoins() {
    this.appService
      .getCoins()
      .subscribe(
        data => this.coins = data.data,
        error => console.log(error)
      );
  }

  coinKeys(coins) {
    return Object.keys(coins);
}

in template :

<tr *ngFor="let k of coinKeys(coins )">
    <td>{{ coins[k].id }}</td>
</tr>

Upvotes: 1

mintquan
mintquan

Reputation: 157

this.coins = data.json() or you can use observable.
in html <div class="card card-inverse" *ngFor="let coin of coins | async">
in component

coins: Observable<Coin[]>;

getCoins() { this.coins = this.coinsService.getCoins(); }

Upvotes: 0

Related Questions