Iterating in form of table in angular

Viewed 1915

I am trying to iterate the list in form of table. The following list should be rendered in the form of table using *ngFor:

I/p :

let list = [
  {
    "key1": {
      "subkey1": [
        1,
        2,
        3,
        1
      ],
      "subkey2": [
        3,
        2,
        3,
        4
      ]
    }
  },
  {
    "key2": {
      "subkey1": [
        1
      ],
      "subkey2": [
        0
      ]
    }
  }
]

Table format (This is how table should render) :

Categories | subkey1 | subkey2

key1       | 1,2,3,1 | 3,2,3,4

key2       |  1      |  0

I tried but its wrong :

Code I tried to iterate in component.html :

 <table border="1">
      <thead>
          <tr>
              <th>Categories</th>
              <th *ngFor="let each of categoriesHeading"> {{each}} </th>  // Array of subkeys
            </tr>
      </thead>
      <tbody *ngFor="let each of categoriesList">
        <tr>
          <td *ngFor="let key of objectKeys(each)">// iterating keys
              {{key}} 
          </td>
          <td> </td> // I don't know how to itereate the values of each subkey of key [1,2,3]
        </tr>
      </tbody>
    </table>

I was not able to share StackBlitz. So I'm sharing this screenshot : enter image description here

Please let me know if something is missing.

3 Answers

You can arrange the data as required and then display it in template.

Try like this:

Working Demo

Controller:

  categoriesHeading = [];
  displayData = [];

  constructor() {
    this.categoriesHeading = Object.keys(this.list[0].key1);

    this.list.forEach(item => {
      let obj = {};
      obj["key"] = Object.keys(item)[0];
      Object.keys(item[Object.keys(item)[0]]).forEach((subkey, i) => {
        obj[subkey] = item[Object.keys(item)[0]][subkey].join();
      });
      this.displayData.push(obj);
    });
  }

Template:

<table border="1">
    <thead>
        <tr>
            <th>Categories</th>
            <th *ngFor="let each of categoriesHeading"> {{each}} </th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let item of displayData">
            <td *ngFor="let each of item | keyvalue"> {{each.value}} </td>
        </tr>
    </tbody>
</table>

NOTE: For Angular 4, if you don't want to use (keyvalue pipe), then do the following.

TS:

objectKeys = Object.keys;

Template:

<table border="1">
    <thead>
        <tr>
            <th>Categories</th>
            <th *ngFor="let each of categoriesHeading"> {{each}} </th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let item of displayData">
            <td *ngFor="let key of objectKeys(item)"> {{item[key]}} </td>
        </tr>
    </tbody>
</table>

While most of the given answers above are correct to the asked question, shall we see a better way to implement this example?

Before looking into better ways, let's see what needs to be improved in your example.

The first thing I see in your provided JSON is that you have hardcoded all the keys in here and if somehow those keys are updated later, then you have to update them in the frontend again. We can avoid that by using generic keys and keeping the labels you need in your table as values.

The next thing is you are adding some of the values in your table from your frontend code. It is good if the app is a static example, but it's recommended to fetch those records from a JSON so you have the freedom to change it as you wish.

Now let's see how you can improve this and get it working.

You can simply update your JSON as follows.

{
  "headers": [
    "Categories",
    "Sub Key 1",
    "Sub Key 2"
  ],
  "data": [
    {
      "properties": [
        {
          "key": "Key 1",
          "key_data": []
        },
        {
          "key": "",
          "key_data": [
            1, 2, 3, 1
          ]
        },
        {
          "key": "",
          "key_data": [
            3, 2, 3, 4
          ]
        }
      ]
    },
    {
      "properties": [
        {
          "key": "Key 2",
          "key_data": []
        },
        {
          "key": "",
          "key_data": [
            1
          ]
        },
        {
          "key": "",
          "key_data": [
            0
          ]
        }
      ]
    }
  ]
}

What I have done here is that you introduced some generic keys and took all the labels you want in your table as values.

You can use the following snippet to display the dataset as you requested in your web application.

<table class="table table-striped">
  <thead>
  <tr>
    <th *ngFor="let header of test_data.headers">{{header}}</th>
  </tr>
  </thead>

  <tbody>
  <tr *ngFor="let row of test_data.data">
    <td *ngFor="let property of row.properties">{{property.key}}{{property.key_data}}</td>
  </tr>
  </tbody>
</table>

You can find the working example here: https://stackblitz.com/edit/iterate-table-form

Hope this helps!

Good Luck!!

Related