0

I'm trying to create a table dynamically with JSON data, including the headers. I used this post to get as far as I've gotten.

My problem is that the data in my table appears completely messed up. I know in my first for each loop I should only iterate through dataMessageResults[0], but that gives me a syntax error.

My results.html:

<div class="play-container">

<h1>Child</h1>
    <table>
         <thead>
              <tr *ngFor="let item of dataMessageResults">           
                <th *ngFor="let item of dataMessageResults | keyvalue">{{item.key}}</th>
              </tr>
         </thead>
         <tbody>
              <tr *ngFor="let item of dataMessageResults">           
                <td *ngFor="let list of item | keyvalue">{{item.value}}</td>
              </tr>
         </tbody>
    </table>

My results.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-message-results',
  templateUrl: './message-results.component.html',
  styleUrls: ['./message-results.component.scss']
})

export class MessageResultsComponent {

  @Input() dataMessageResults: Object;

  constructor() { }

}

an example of the data. Angular seems to add a number for each JSON which is resulting in the numbers in the headers.

{
    "elemNb": "",
    "msgID": "",
    "year": "2019",
    "week": "42",
    "sysDatetime": "2019-10-16T11:57:34.748Z",
    "airline": "EJU",
},
{
    "elemNb": "",
    "msgID": "",
    "year": "2019",
    "week": "42",
    "sysDatetime": "2019-10-16T11:57:35.296Z",
    "airline": "DLH",
},
{
    "elemNb": "",
    "msgID": "",
    "year": "2019",
    "week": "42",
    "sysDatetime": "2019-10-16T11:59:48.599Z",
    "airline": "BAW",
    "tail": " ",

What am I doing wrong?

Aras
  • 1,599
  • 15
  • 25
khansen
  • 205
  • 1
  • 6
  • 16
  • i'm assuming you created the custom pipe like that other post did and named it keyvalue? – Wen W Oct 16 '19 at 13:20

4 Answers4

2

Why do you want to iterate over an object? Your data should be an array! Then you can calculate your headers easily:

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-message-results',
  templateUrl: './message-results.component.html',
  styleUrls: ['./message-results.component.scss']
})

export class MessageResultsComponent {

  @Input() dataMessageResults: any[];

  constructor() { }

  getHeaders() {
    let headers: string[] = [];
    if(this.dataMessageResults) {
      this.dataMessageResults.forEach((value) => {
        Object.keys(value).forEach((key) => {
          if(!headers.find((header) => header == key)){
            headers.push(key)
          }
        })
      })
    }
    return headers;
  }
}
<div class="play-container">

<h1>Child</h1>
    <table border>
         <thead>
              <tr>           
                <th *ngFor="let header of getHeaders()">{{header}}</th>
              </tr>
         </thead>
         <tbody>
              <tr *ngFor="let item of dataMessageResults">           
                <td *ngFor="let key of getHeaders()">{{item[key]}}</td>
              </tr>
         </tbody>
    </table>
JuNe
  • 1,911
  • 9
  • 28
  • you're right. It should be an array and it is. I've been thinking about it the wrong way! Unfortunately your getHeaders method didnt work. At least im heading in the right direction now. – khansen Oct 16 '19 at 13:39
  • I made some changes and it is working now: https://stackblitz.com/edit/angular-dynamic-table-header – JuNe Oct 16 '19 at 14:06
  • wow. this is much better and more testable than my solution which involved slicing arrays in order to iterate through only the first object. Thanks – khansen Oct 16 '19 at 14:32
0

<div class="play-container">

<h1>Child</h1>
    <table>
         <thead>
              <tr>           
                <th *ngFor="let list of dataMessageResults">{{list.key | keyvalue}}</th>
              </tr>
         </thead>
         <tbody>
              <tr *ngFor="let item of dataMessageResults">           
                <td *ngFor="let list of item ">{{list.value | keyvalue}}</td>
              </tr>
         </tbody>
    </table> 

update my answer,please check it.

Pushprajsinh Chudasama
  • 7,772
  • 4
  • 20
  • 43
  • this returns an error. "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays." – khansen Oct 16 '19 at 13:34
0

I've almost gotten it to work with

<h1>Child</h1>
        <table>
             <thead>
                  <tr *ngFor="let message of dataMessageResults">           
                    <th *ngFor="let item of message | keyvalue">{{item.key}}</th>
                  </tr>
             </thead>
             <tbody>
                  <tr *ngFor="let message of dataMessageResults">           
                    <td *ngFor="let item of message | keyvalue">{{item.value}}</td>
                  </tr>
             </tbody>
        </table>

But I cannot figure out how I can specify that I only want to iterate through the headers once.

<tr *ngFor="let message of dataMessageResults[0]">

does not work.

khansen
  • 205
  • 1
  • 6
  • 16
-1

<h1>Child</h1>
    <table>
         <thead>
              <tr *ngFor="let item of dataMessageResults | keyvalue">           
                <th>{{item.key}}</th>
              </tr>
         </thead>
         <tbody>
              <tr *ngFor="let item of dataMessageResults | keyvalue">           
                <td>{{item.value}}</td>
              </tr>
         </tbody>
    </table>
upinder kumar
  • 819
  • 6
  • 8