Reputation: 1733
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
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
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
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
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
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