error display in *ngfor json array object

Rafi picture Rafi · Apr 25, 2016 · Viewed 27k times · Source

when fetching json array object from rest api and trying to display in ngfor failed with the reason

error

EXCEPTION: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. in [indexes in HomeComponent@5:37]

Code

import {Component} from 'angular2/core';
import {HomeService} from './home.services';
import {Index} from './index';

@Component({
    selector: 'home-app',
    providers: [HomeService],

    template: `
        <section class="left_side">
            <article>
                <div class="div_home">
                    <div class="div_homeIndxPartition">
                        <div class="div_IndxPartition" *ngFor="#indObj of indexes">
                            <table width="500px" class="idx_cons_table_det">
                                <tr>
                                    <th align="center" color="#A9F5F2"><h3>{{indObj.name}} ({{indObj.tracker}})</h3></th>
                                    <th align="center">Value</th>
                                    <th align="center">Change</th>
                                    <th align="center">%</th>
                                </tr>
                                <tr>
                                    <td align="center" colspan="1"></td>
                                    <td align="center">{{indObj.value}}</td>
                                    <td align="center">{{indObj.change}}</td>
                                    <td align="center">{{indObj.percent}}%</td>
                                </tr>
                            </table>
                            <br/>
                            <table width="500px" class="idx_cons_table">
                                <tr>
                                    <th align="center">High</th>
                                    <th align="center">Low</th>
                                    <th align="center">Open</th>
                                    <th align="center">Close</th>
                                    <th align="center">52 Week High</th>
                                    <th align="center">52 Week Low</th>                             
                                </tr>
                                <tr>
                                    <td align="center">{{indObj.high}}</td>
                                    <td align="center">{{indObj.low}}</td>
                                    <td align="center">{{indObj.open}}%</td>
                                    <td align="center">{{indObj.close}}</td>
                                    <td align="center">{{indObj.yearHigh}}</td>
                                    <td align="center">{{indObj.yearLow}}%</td>
                                </tr>
                            </table>                        
                        </div>                      
                    </div>
                </div>
            </article>
        </section>
    `

})
export class HomeComponent {
    public indexes:Array<Index>=[];
    public error;

constructor(private _service: HomeService){
    this.indexes = _service.getIndexes().subscribe(
            data => this.indexes =  JSON.parse(data),
            error => alert(" Error is : " + error),
            ()=> console.log("finished")
         );
    console.log(this.indexes);
}
}

JSON Data

[
  {
    "id": 1,
    "name": "FTSE 100",
    "ticker": "UKX",
    "value": 69875.23,
    "change": 100,
    "percent": 2.3,
    "high": 69875.23,
    "low": 69700.89,
    "yearHigh": 699999.23,
    "yearLow": 680005.23,
    "open": 69600.54,
    "close": 699000.97,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 2,
    "name": "FTSE 250",
    "ticker": "MCX",
    "value": 465820.85,
    "change": 100,
    "percent": 2.3,
    "high": 465880.12,
    "low": 465810.74,
    "yearHigh": 478990.34,
    "yearLow": 465320.23,
    "open": 69600.54,
    "close": 699000.97,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 3,
    "name": "FTSE All-Share",
    "ticker": "ASX",
    "value": 236549.23,
    "change": 100,
    "percent": 2.3,
    "high": 236949.23,
    "low": 236149,
    "yearHigh": 246949.21,
    "yearLow": 235549.29,
    "open": 236519.23,
    "close": 236649.23,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 4,
    "name": "Euro Stoxx 50",
    "ticker": "STOXX50E",
    "value": 123469.87,
    "change": 100,
    "percent": 2.3,
    "high": 123499.87,
    "low": 123439.87,
    "yearHigh": 123499.87,
    "yearLow": 123169.87,
    "open": 123465.87,
    "close": 123459.87,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 5,
    "name": "S&P 500 ",
    "ticker": "S500",
    "value": 358976.36,
    "change": 100,
    "percent": 2.3,
    "high": 358986.36,
    "low": 358946.36,
    "yearHigh": 359976.36,
    "yearLow": 357976.36,
    "open": 358970.36,
    "close": 358996.36,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 6,
    "name": "Dow Jones I.A.",
    "ticker": "INDU",
    "value": 456789.36,
    "change": 100,
    "percent": 2.3,
    "high": 456799.36,
    "low": 456779.36,
    "yearHigh": 456889.36,
    "yearLow": 456689.36,
    "open": 456729.36,
    "close": 456779.36,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 7,
    "name": "GOLD",
    "ticker": "",
    "value": 500,
    "change": 100,
    "percent": 2.3,
    "high": 700,
    "low": 300,
    "yearHigh": 1500,
    "yearLow": 350,
    "open": 450,
    "close": 470,
    "constituents": null,
    "runDate": "21/04/2015"
  },
  {
    "id": 8,
    "name": "Brent Crude",
    "ticker": "",
    "value": 112,
    "change": 100,
    "percent": 2.3,
    "high": 115,
    "low": 107,
    "yearHigh": 200,
    "yearLow": 72,
    "open": 110,
    "close": 115,
    "constituents": null,
    "runDate": "21/04/2015"
  }
]

Answer

Thierry Templier picture Thierry Templier · Apr 25, 2016

I think that the value you set in the indexes property isn't an array but an object.

I would see several reasons for this:

  • You receive the response instead of the payload from the getIndexes method. In this case, you could use the map operator in this method:

    getIndexes() {
      return this.http.get(...).map(res => res.json());
    }
    
  • The received payload doesn't correspond to an array but some of its properties. In this case, you need to set this property into the indexes property.

If you want to iterate over the properties of an object, you need to implement a custom filter like this:

@Pipe({name: 'keyValues'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]);
    }
    return keys;
  }
}

and use it like that:

<div class="div_IndxPartition" *ngFor="#indObj of indexes | keyValues">
  (...)
</div>

See this question: