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?

1
  • i'm assuming you created the custom pipe like that other post did and named it keyvalue? Commented Oct 16, 2019 at 13:20

4 Answers 4

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>
Sign up to request clarification or add additional context in comments.

3 Comments

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.
I made some changes and it is working now: stackblitz.com/edit/angular-dynamic-table-header
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
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.

Comments

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.

1 Comment

this returns an error. "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."
-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>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.