Home > database >  How to display from JSON object to DOM table where table column is based on JSON Keys
How to display from JSON object to DOM table where table column is based on JSON Keys

Time:10-05

So I have this JSON object:

[
{
    "SysID": "4",
    "Defect Classification": "Wrong Image Color",
    "1": "3.0",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "5",
    "Defect Classification": "Wrong Outer Liner Color",
    "1": "3.0",
    "2": "",
    "3": "",
    "4": "3.0",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "3.0",
    "12": ""
},
{
    "SysID": "6",
    "Defect Classification": "Critical Print Misalignment",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "7",
    "Defect Classification": ">15% Hole Placement Misalignment",
    "1": "",
    "2": "",
    "3": "3.0",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "8",
    "Defect Classification": "Delamination",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "9",
    "Defect Classification": "Misaligned Lamination",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "10",
    "Defect Classification": "Poor Gluetab adhesion",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "11",
    "Defect Classification": "Skewing",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
},
{
    "SysID": "12",
    "Defect Classification": "Panel Overlapping",
    "1": "",
    "2": "",
    "3": "",
    "4": "",
    "5": "",
    "6": "",
    "7": "",
    "8": "",
    "9": "",
    "10": "",
    "11": "",
    "12": ""
}
]

Now the object keys are not always the same. The numbers have a range from 1 to n. How to display this dynamically in a table??

This is my code so far:

component.ts

criticalData: any[] = [];
tableHeader: any[] = [];
this.apiservice.loadPrintDetail(id).subscribe({
    next: (data: any) => {
        this.criticalData = data;
        this.tableHeader = Object.keys(data[0]);
    }
})

component.html

<table  id="criticalTable">
                <thead>
                    <tr>
                        <th *ngFor="let item of tableHeader">{{item}}</th>
                    </tr>
                </thead>
                <tbody>
                    <tr *ngFor="let item of criticalData; let idx = index">
                        <td *ngFor="let row of criticalData; let ix = index">{{item[ix]}}</td>
                    </tr>
                </tbody>
            </table>

The result is this: Result

As you can see the result is so wrong. How to correct this? The SysID should be in the first column, Defect Classification should be in the second and columns 1 to n should be next. How to achieve this?

CodePudding user response:

I can pretty much guarantee that that is the order your data is coming in. You should set a breakpoint or console log the data to sure.

If you have no control over how the data arrives (what you present above isn't super convenient), then you'll have to transform the data in code, probably in your loadPrintDetail() subscription.

BTW you should unsubscribe from your observables or use a .pipe(take(1)) to avoid a memory leak.

CodePudding user response:

Object.keys() does not guarantee that the columns order will be the same, as in the original object. See here: Does JavaScript guarantee object property order?

I would suggest you to use the | keyvalue pipe in your html template to achieve the thing you want. I believe the pipe will not change the order of the columns, for sure, you can use compare function to keep the original order. See here: angular keyvalue pipe sort properties / iterate in order

CodePudding user response:

You can add an array indicating SysID and Defect Classification as the first columns followed by the indexes.

For the header, you populate the columns. For the rows and items, you nest for loop the items, but displaying only the item based on the column header

<table  id="criticalTable">
<thead>
    <tr>
        <th *ngFor="let item of columns">{{item.name}}</th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let item of items">
        <td *ngFor="let item2 of columns">
          <div>
            {{item[item2.name]}}
          </div>
        </td>
    </tr>
</tbody>
</table>

On the typescript file, you assign the column index for each header. And assign the remaining indexes as the succeeding indexes.

  columns: any[] = [
    {
      columnNo: 0,
      name: 'SysID',
    },
    {
      columnNo: 1,
      name: 'Defect Classification',
    },
  ];

  ngOnInit() {
    let noOfColumns = 12;
    let numberedColumns = [...Array(noOfColumns).keys()].map((item) => {
      return {
        columnNo: this.columns.length   item,
        name: item   1,
      };
    });
    this.columns = [...this.columns, ...numberedColumns];
  }

You can check this link I created https://angular-mxcyxg.stackblitz.io

CodePudding user response:

As Christian Joseph Dalisay stated, Following is the simple way to do:

//Get First Object from array
let rawCols = data[0];
//Add default two columns
tableHeader: any = ["SysID", "Defect Classification"];
//Add the rest dynamic columns
for(var key in rawCols){
       if(tableHeader.indexOf(key) === -1) 
         tableHeader.push(key);
    }

//Front end
<table  id="criticalTable">
<thead>
    <tr>
        <th *ngFor="let item of tableHeader">{{item}}</th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let item of items">
        <td *ngFor="let cols of columns">
          <div>
            {{item[cols]}}
          </div>
        </td>
    </tr>
</tbody>
</table>

CodePudding user response:

HTML.

<table  id="criticalTable">
    <thead>
        <tr>
            <th *ngFor="let item of data[0] | keyvalue : keyDescOrder"> {{item.key}}</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let item of data">
            <td *ngFor="let item2 of item|keyvalue : keyDescOrder">
                <div>
                    {{item2.value}}
                </div>
            </td>
        </tr>
    </tbody>
</table>


TS.
import { KeyValue } from '@angular/common';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-example1',
  templateUrl: './example1.component.html',
  styleUrls: ['./example1.component.css']
})
export class Example1Component implements OnInit {
 
  // Order by descending property key
  constructor() { }

  data: any = [
    {
      "SysID": "4",
      "Defect Classification": "Wrong Image Color",
      "1": "3.0",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "5",
      "Defect Classification": "Wrong Outer Liner Color",
      "1": "3.0",
      "2": "",
      "3": "",
      "4": "3.0",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "3.0",
      "12": ""
    },
    {
      "SysID": "6",
      "Defect Classification": "Critical Print Misalignment",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "7",
      "Defect Classification": ">15% Hole Placement Misalignment",
      "1": "",
      "2": "",
      "3": "3.0",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "8",
      "Defect Classification": "Delamination",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "9",
      "Defect Classification": "Misaligned Lamination",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "10",
      "Defect Classification": "Poor Gluetab adhesion",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "11",
      "Defect Classification": "Skewing",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    },
    {
      "SysID": "12",
      "Defect Classification": "Panel Overlapping",
      "1": "",
      "2": "",
      "3": "",
      "4": "",
      "5": "",
      "6": "",
      "7": "",
      "8": "",
      "9": "",
      "10": "",
      "11": "",
      "12": ""
    }
  ]
  ngOnInit(): void {
    // this.data = this.data.sort();
    console.log(this.data);
    
  }

  keyDescOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
    if(isNaN(a.key)){
      return a.key > b.key ? -1 : (b.key > a.key ? 1 : 0);
    }else{
       return 1;
     }
  }

}
  • Related