4

In ngx-data table how to loop through nested Json object in ngx -data table.

json sample object:

rows = [
{ name: 'Austin', gender: 'Male', company: 'Swimlane', topings:[
 { id:'101',name:'spinach'}]
 },
{ name: 'Dany', gender: 'Male', company: 'KFC',topings:[
 { id:'102',name:'onion'}] },
{ name: 'Molly', gender: 'Female', company: 'Burger King' ,topings:[
 { id:'103',name:'ginger'}]},

];

In ngx-datatable how I need to loop through topings in above json object and display toping data in data table. could any one please answer how I have to do it....??

Mounica
  • 170
  • 1
  • 4
  • 14
  • hi, what are the header names/properties that you want to use on your datatable? – wentjun Mar 22 '19 at 01:27
  • Also, are you trying to display everything on a row, or are you planning to use row-details to display the nested `topings` – wentjun Mar 22 '19 at 01:38
  • I want to display every thing in a row not in row detail. I Want to display name|gender|company|topings.name ...like this I want to display using ngx datatable. usually for normal table I use ngFor to iterate through objects.objetcs. but in ngx data table how I need to do....? – Mounica Mar 22 '19 at 13:42
  • Ok, I have produced my answer. It should work, as this is what I have always been doing when i use ngx-datatable. – wentjun Mar 22 '19 at 14:34

2 Answers2

7

Alright, what I am thinking is that, you will need to do some manipulation on your data before you can render it on your datatable.

On your component.ts, first, you should define your columns.

tableColumns = [
  {
    prop: 'name',
    name: 'Name'
  },
  {
    prop: 'gender',
    name: 'Gender'
  },
  {
    prop: 'company',
    name: 'Company'
  },
  {
    prop: 'topingsId',
    name: 'Topings ID'
  }, 
  {
    prop: 'topingsName',
    name: 'Topings Name'
  }
]

Next, you should attempt to 'flatten' that your data such that it an array of single-level objects (instead of having them nested).

this.rows = [
  { 
    name: 'Austin', gender: 'Male', company: 'Swimlane', topings:[{ id:'101',name:'spinach'}]
  },
  { 
    name: 'Dany', gender: 'Male', company: 'KFC',topings:[{ id:'102',name:'onion'}] 
  },
  { 
    name: 'Molly', gender: 'Female', company: 'Burger King' ,topings:[{ id:'103',name:'ginger'}]
  }
];

this.rows = this.rows.map(row => ({
  name: row['name'],
  gender: row['gender'],
  company: row['company'],
  topingsId: row['topings'][0]['id'],
  topingsName: row['topings'][0]['name']
}));

console.log(this.rows);

Last but not least, on your component.html, you can render your datatable as such:

<ngx-datatable class="material" [rows]="rows" [columns]="tableColumns"....></ngx-datatable>

And don't forget to define the other properties that your table will need.


Additional ways to assign your row data using some ES6 magic.

1) Using the Spread Syntax:

this.rows = this.rows.map(row => ({
  ...row,
  topingsId: row['topings'][0]['id'],
  topingsName: row['topings'][0]['name']
}));

2) Using both the Spread Syntax and Object Destructuring:

this.rows = this.rows.map(row => {
  const {topings, ...others} = row;
  return {
    ...others,
    topingsId: row['topings'][0]['id'],
    topingsName: row['topings'][0]['name']
  };
});

And to answer your question on the comments, our datatable rows and columns are dynamic, we have to adopt a slightly different strategy.

First, we flatten your data to an array of unnested objects. We get an array of the topings for each row, and then we convert the array into an object. After which, we use the spread synxtax to join everything into one object, which represents a row within this.rows.

Take note that we are making use of Computed Property Names (yet another ES6 feature) to provide the dynamic property key of each toping.

this.rows = this.rows.map(row => {
  const {topings, ...others} = row;
  const topingsList = topings.map((toping, index) => ({
    ['toping' + Number(index + 1) + ' Name']: toping['name']
  }));
  topingsObject = Object.assign({}, ...topingsList);
  return { 
    ...others,
    ...topingsObject
  }
});

Next, from the rows data, we have to gather the array of new columns which is one of the required properties of ngx-datatable. First, our this.tableColumns is defined as such:

tableColumns = [
  {
    prop: 'name',
    name: 'Name'
  },
  {
    prop: 'gender',
    name: 'Gender'
  },
  {
    prop: 'company',
    name: 'Company'
  }
];

And right after we have obtained the flattened this.rows, we will obtain an array of the properties that are available within the row data. From there, we update the tableColumns with the dynamic toppings (eg. Toping1 Name, Toping2 Name, ..etc)

this.rows = this.rows.map(row => { .....}) // continued from the above

const headerNames = Object.keys(Object.assign({}, ...this.rows));
headerNames.map(header => {
  if (header!=='name' && header!=='gender' && header!=='company') {
    this.tableColumns.push({
      prop: header,
      name: header
    });
  }
});
wentjun
  • 40,384
  • 10
  • 95
  • 107
  • Thanks @wentjun , I wil try and let you know . Thank you so much for your response – Mounica Mar 22 '19 at 14:54
  • this.rows = [ { name: 'Austin', gender: 'Male', company: 'Swimlane', topings:[{ id:'101',name:'spinach'},{id:'110',name:'pineapple'}] }, { name: 'Dany', gender: 'Male', company: 'KFC',topings:[{ id:'102',name:'onion'}] }, { name: 'Molly', gender: 'Female', company: 'Burger King' ,topings:[{ id:'103',name:'ginger'}] } ]; suppose one row has multiple toppings we need to store it in array of toppings in row. how we do. In above ode we are taking only zeroth index[0] . – Mounica Mar 22 '19 at 16:25
  • and above code is working perfectly for zeroth topping , Thanks @wentjun – Mounica Mar 22 '19 at 16:31
  • Hmmm, do you want to store the all of the toppings in the same column for each row? Or do you want to store each topping object in a different column? – wentjun Mar 22 '19 at 16:49
  • for each row I want to display all toppings information eg: name|gender|company|topping1 name , topping2 name – Mounica Mar 22 '19 at 17:14
  • I see.. You only need topping name on the columns, right? No need for topping id? – wentjun Mar 22 '19 at 17:42
  • yes I need only names, this is just example I took , but my real json object is huge. table example: name|company|topping1Name, topping2 Name – Mounica Mar 22 '19 at 17:52
  • Ok, I have just updated my answer. Hope I was clear in my explanation hah – wentjun Mar 22 '19 at 18:25
  • 2
    This answer was super helpful. This is definitely a way for dynamic table rows. – subodhkalika Aug 03 '20 at 23:47
2

Well I think there is a simpler way and yes it's very simple. Just do the following:

Let's imagine you have a nested json object like this:

    data = {
        "id": 1,
        "name": "John Doe"
        "comments": [
            {"id":1, "content": "Some content" },
            {"id":2, "content": "Some content" }
        ]
    };

In your HTML template:

<ngx-datatable-column name="Comment" prop="comments">
    <ng-template let-value="value" ngx-datatable-cell-template>
        <span>{{value.content}}</span>
    </ng-template>  
</ngx-datatable-column>
faye.babacar78
  • 774
  • 7
  • 12