3

Yes, I see that other people get this error , I just don't quite get how to fix it in my code

private _url = 'https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,LTC,EOS,DASH&tsyms=USD'

If I didn't have the return it does not crash with the error , but I do want to return the data.

I have a component that calls up this method ( in this service ts file )

Subscriber:

getAllCoins() {

    var blah = [];

    return this.getCoins().subscribe(
        data => {
            blah = data;               
            //console.log('subscriber coins', blah)
        }
    )

}

Calls this code

getCoins() {
    return this.http.get(this._url)
        .map((response: Response) => response.json())
        //.do(data => console.log(data))
        .do(data => console.log('All: ' + JSON.stringify(data)))  // do operator to peek 
        .catch(this.handleError);
}

Now, I see that the data from the url looks like this

{
"BTC": {
  "USD": 3349.1
},
"ETH": {
  "USD": 296.3
},
"LTC": {
  "USD": 47.56
},
"EOS": {
  "USD": 1.83
},
"DASH": {
  "USD": 195.83
}
}

How can I prevent from getting this error errors.ts:42 ERROR Error: Uncaught (in promise): Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

UPDATE for comment question

@Component({
template: `
<div>test</div>
<div *ngFor="let coin of coinsList">
 abc
 </div>
`
})
  • Does it return one object always or is there a possibility of returning an array ? – Vikhyath Maiya Aug 10 '17 at 05:48
  • You don't need an array, can implement you own iterable on an object very easily https://stackoverflow.com/a/45321622/2545680 – Max Koretskyi Aug 10 '17 at 05:48
  • Can you help show me, I don't quite get this –  Aug 10 '17 at 05:54
  • @JohnBaxter, how do you use `blah` in the template and how do you expect to see the rendered `html`? Show in your question – Max Koretskyi Aug 10 '17 at 06:04
  • @Maximus - trying to use it like in my updated question showing that code for the template thx –  Aug 10 '17 at 06:13
  • @JohnBaxter, there's no `coinsList` in your code. Can you be more specific? What data will you be using from `coinsList` in your html, the `abc` doesn't tell much – Max Koretskyi Aug 10 '17 at 06:17
  • `this.coinsList = this.coinService.getAllCoins()` abc is placeholder , if it truly looped over the data returned it would repeat abc for each .. –  Aug 10 '17 at 06:21
  • I can't seem to get past this return of the type of data though - observables –  Aug 10 '17 at 06:21
  • The data returned from the URL is an object, not an array. The format of your data returned from service should be contained in square brackets e.g. `[{...},{...}]` – Brad Aug 10 '17 at 06:47
  • Where have you seen an example/tutorial that uses ngFor over an observable like this? – eko Aug 10 '17 at 07:21
  • @Brad - how do I get the data into brackets? –  Aug 10 '17 at 08:27
  • @echonax `*ngFor='let product of products` from here `https://github.com/DeborahK/Angular2-GettingStarted/blob/master/APM%20-%20Final/app/products/product-list.component.html` –  Aug 10 '17 at 08:39

2 Answers2

10

As others have said, *ngFor only works on iterables.

There are a couple of methods that can be done to overcome this problem. Ones that come to my mind right now are:

1) You can push your list of objects to an Array.

this._ConfigurationService.getCoins()
            .subscribe(
            (data)=> {
                for(let key in data){
                  this.coinsList.push(data[key]);
                }
            },
            (error) => console.log("error : " + error)
        );

template:

<div *ngFor="let coin of coinsList">
    <span>{{coin | json}}</span>
</div>

Full plunker example: http://plnkr.co/edit/zrzVF8qKl8EvKKp2Qt45?p=preview

2) You can convert the response from object to an iterable using a pipe as shown in here: How to iterate [object object] using *ngFor in Angular 2

3) You can implement the iterable function to your object as shown here: Angular NgFor only supports binding to Iterables such as Arrays.

4) You can create special directive as shown here: Can ngForIn be used in angular 4?

My suggestion would be to use the first one for simplicity.

eko
  • 39,722
  • 10
  • 72
  • 98
  • For some reason I am getting an error ERROR TypeError: Cannot read property 'push' of undefined I'm doing the same thing in which I subscribe to the service –  Aug 15 '17 at 06:41
  • Oh, the only different is that if I set `coinsList:[]` , then the `this.coinsList.push(data[key]) show error of `Argument of type 'any' is not assignable to parameter of type 'never'` , so I changed to `coinsList:any; no visual errors - but the push error which I suppose makes sense with an array .. ugh how come your plunker works –  Aug 15 '17 at 06:45
  • 1
    @JohnBaxter you are probably not initializing `coinsList`. I've initialized it in the fields `coinsList = [];` you are just declaring its type with `coinsList:[];`. That is, `:` and `=` is not the same operation. Spot the differences between the two pictures :-) – eko Aug 15 '17 at 06:54
  • Yes, - cool it works - I am liking typescript, just not thinking about javascript ha thx again –  Aug 15 '17 at 07:08
  • @JohnBaxter no problem :-) – eko Aug 15 '17 at 07:09
  • - I didn't get a chance to get back to working out how to format my data , I hate the API returned data I posted a question here thx if you have time https://stackoverflow.com/questions/45727951/angular-4-display-data-that-is-in-this –  Aug 17 '17 at 06:27
1

As the erorr says you are trying to do a ngFor over Object, it works over any iterables.

Probably you can iterate over them and create an array, and then use it for the ngFor.

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • it works over any iterables, not just an array https://stackoverflow.com/a/45321622/2545680 – Max Koretskyi Aug 10 '17 at 05:49
  • Wait, how can I do this? Seem like i'm doing things fine with subscriber and the method it calls , or is there a better way of writing that code ? –  Aug 10 '17 at 05:53
  • I see that some people use Observable and do not even use subscribe - can/should I change my code, how ? `getProducts(): Observable { return this._http.get(this._productUrl) .map((response: Response) => response.json()) .do(data => console.log('All: ' + JSON.stringify(data))) .catch(this.handleError); }` –  Aug 10 '17 at 06:14