Search code examples
angularangular-directive

How to show JSON in HTML table on Angular 10


I'm trying to show data in HTML table on Angular 10 and I get this error Error trying to diff '[object Object]'. Only arrays and iterables are allowed. I have this JSON below:

{
    "Meta Data": {
        "1. Information": "Daily Prices (open, high, low, close) and Volumes",
        "2. Symbol": "petr4.SA",
        "3. Last Refreshed": "2020-10-23",
        "4. Output Size": "Compact",
        "5. Time Zone": "US/Eastern"
    },
    "Time Series (Daily)": {
        "2020-10-23": {
            "1. open": "20.9400",
            "2. high": "21.1400",
            "3. low": "20.5400",
            "4. close": "20.5700",
            "5. volume": "61328500"
        },
        "2020-10-22": {
            "1. open": "20.1000",
            "2. high": "20.8400",
            "3. low": "20.0500",
            "4. close": "20.8400",
            "5. volume": "98359400"
        }
}

My model class:

export class Candle{
    date: Date;
    open: string;
    high: string;
    low: string;
    close: string;
    volume: string;
}

My service class:

export class CandleService {

  constructor(
    public http: HttpClient
  ) { }

  findAll(): Observable<Candle[]>{
    return this.http.get<Candle[]>(`${API_CONFIG.baseUrl}`);
  }
}

and lastly HTML:

<div class="container-analyzer">
    <table>
        <thead>
          <th>Date</th>
          <th>Open</th>
          <th>High</th>
          <th>Low</th>
          <th>Close</th>
          <th>Volume</th>
        </thead>
        <tbody *ngFor="let candle of ativoData">
            <tr>
                <td>{{candle.data}}</td>
                <td>{{candle.open}}</td>
                <td>{{candle.high}}</td>
                <td>{{candle.low}}</td>
                <td>{{candle.close}}</td>
                <td>{{candle.volume}}</td>
            </tr>
        </tbody>
      </table>
</div>

Solution

  • You need a function to transform your data into an array so that it can be displayed on the template.

    Write a function like this

      transformData(rawData: any) {
        let processedData: Array<Candle> = [];
        Object.keys(rawData["Time Series (Daily)"] || []).forEach(key => {
          processedData.push({
            date: new Date(key),
            open: rawData["Time Series (Daily)"][key]["1. open"],
            high: rawData["Time Series (Daily)"][key]["2. high"],
            low: rawData["Time Series (Daily)"][key]["3. low"],
            close: rawData["Time Series (Daily)"][key]["4. close"],
            volume: rawData["Time Series (Daily)"][key]["5. volume"]
          });
        });
        return processedData;
      }
    

    and call it once the data is received from the service

    something like

    this.ativoData = this.transformData(this.rawData);
    

    and in temple

    <div class="container-analyzer">
        <table>
            <thead>
                <th>Date</th>
                <th>Open</th>
                <th>High</th>
                <th>Low</th>
                <th>Close</th>
                <th>Volume</th>
            </thead>
            <tbody *ngFor="let candle of ativoData">
                <tr>
                    <td>{{candle.date | date}}</td>
                    <td>{{candle.open}}</td>
                    <td>{{candle.high}}</td>
                    <td>{{candle.low}}</td>
                    <td>{{candle.close}}</td>
                    <td>{{candle.volume}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    

    Here is a working sample