skip to Main Content

I have a 2D array within my Javascript. The array is assigned the variable ‘arr’ and looks like this:

[
  [
    "0",
    {
      cat_id: "1",
      cat_name: "Tiger",
    },
  ],
  [
    "1",
    {
      cat_id: "2",
      cat_name: "Lion",
    },
  ],
  [
    "2",
    {
      cat_id: "3",
      cat_name: "Cheetah",
    },
  ],
  [
    "3",
    {
      cat_id: "5",
      cat_name: "Leopard",
    },
  ],
]

I want to give the user a neat little HTML table on screen, with the keys being the header and the values being the rows, thus:

cat_id cat_name
1 Tiger
2 Lion
3 Cheetah
4 Leopard

I’ve been looking at many articles on StackOverflow and the web in general, but I’m not a Javascript expert and, honestly, I can’t get anything to work. Any help greatly appreciated!

My HTML contains the empty table code:

const arr = [["0", { cat_id: "1", cat_name: "Tiger", },], ["1", { cat_id: "2", cat_name: "Lion", },], ["2", { cat_id: "3", cat_name: "Cheetah", },], ["3", { cat_id: "5", cat_name: "Leopard", },],]

var tableBody = document.getElementById("wrap");
tableBody.innerHTML = "";
arr.forEach(function (row) {
  var newRow = document.createElement("tr");
  tableBody.appendChild(newRow);
  if (row instanceof Array) {
    row.forEach(function (cell) {
      var newCell = document.createElement("td");
      newCell.textContent = cell;
      newRow.appendChild(newCell);
    });
  } else {
    newCell = document.createElement("td");
    newCell.textContent = row;
    newRow.appendChild(newCell);
  }
});
<table id="wrap"></table>

Because arr is a 2D array, right now my code just produces this as a table:

0   [object Object]
1   [object Object]
2   [object Object]
3   [object Object]

I understand why this is happening, but my JS are simply not good enough to get the result I’m trying to achieve.

Edit

The properties of the nested objects won’t be known ahead of time so the solution needs to be dynamic.

eg:

arr = [
  ["0", { dog_id: "8866", dog_colour: "Brown", dog_desc: "Small, bit grumpy" }],
  ["1", { dog_id: "8867", dog_colour: "Black", dog_desc: "Nice dog" }],
  ["2", { dog_id: "8868", dog_colour: "Brown", dog_desc: "Dead" }],
  ["3", { dog_id: "8869", dog_colour: "Blonde", dog_desc: "Barks a lot" }],
];

2

Answers


  1. Here is the working example:

    let arr = [
            [
              "0",
              {
                id: "1",
                name: "ABC",
              },
            ],
            [
              "1",
              {
                id: "2",
                name: "DEF",
              },
            ],
            [
              "2",
              {
                id: "3",
                name: "TEST",
              },
            ],
            [
              "3",
              {
                id: "5",
                name: "SOME",
              },
            ],
          ];
    
          let tableId = document.getElementById("table1");
    
          arr.map((elem) => insertRow(tableId, elem[1]));
    
          function insertRow(tableId, colVal) {
            //way to insert at last row
            var row = tableId.insertRow(-1);
            //first cell (column)
            var cell1 = row.insertCell(0);
            //seconds cell (column)
            var cell2 = row.insertCell(1);
            //column text
            cell1.innerHTML = colVal.id;
            cell2.innerHTML = colVal.name;
          }
    table {
          font-family: arial, sans-serif;
          border-collapse: collapse;
          width: 100%;
        }
    
        td,
        th {
          border: 1px solid #dddddd;
          text-align: left;
          padding: 8px;
        }
    
        tr:nth-child(even) {
          background-color: #dddddd;
        }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
    
      <body>
        <table id="table1">
          <tr>
            <th>Company</th>
            <th>Contact</th>
          </tr>
        </table>
    
      </body>
    </html>
    Login or Signup to reply.
  2. Here is a slightly more robust solution, which will accommodate objects with different numbers of properties, and avoids the need to sort the keys by using a single array of column header keys to access each successive row’s properties.

    It first gathers all the Object.keys of all the nested objects and uses these to build the header row. It then iterates over each object in the original array and uses the accumulated column keys to access the properties to build the value rows. If the property is not present in the object it uses nullish coallescing ?? to assign an empty string to the column for that row.

    const arr = [
      ["0", { cat_id: "1", cat_name: "Tiger" }],
      ["1", { cat_id: "2", cat_name: "Lion", "cat_desc": "Roars"}],
      ["2", { cat_id: "3", cat_name: "Cheetah" }],
      ["3", { cat_id: "5", cat_name: "Leopard" }],
    ];
    
    const columns = new Set(arr.flatMap(([, obj]) => Object.keys(obj)));
    
    var tableBody = document.getElementById("wrap");
    tableBody.innerHTML = "";
    
    const headerRow = document.createElement("tr");
    tableBody.appendChild(headerRow);
    for (const column of columns) {
      const newCell = document.createElement("td");
      newCell.textContent = column;
      headerRow.appendChild(newCell);
    }
    
    for (const [, obj] of arr) {
      const newRow = document.createElement("tr");
      tableBody.appendChild(newRow);
      for (const column of columns) {
        const newCell = document.createElement("td");
        newCell.textContent = obj[column] ?? "";
        newRow.appendChild(newCell);
      }
    }
    <table id="wrap"></table>

    see:

    Original answer

    Here is an example that iterates the Object.entries of each nested data object to first build a header row from the keys, and then data rows from the values. This assumes that any further columns will be added as properties to the single object at index 1 of the nested arrays.

    It first maps the original array to be an 2d array of [key, value] tuples and sorts each array of tuples by key. It then iterates the keys of the first element in the array to create a header. It then proceeds to iterate each element in the array to build each data row.

    const arr = [
      ["0", { cat_id: "1", cat_name: "Tiger" }],
      ["1", { cat_id: "2", cat_name: "Lion" }],
      ["2", { cat_id: "3", cat_name: "Cheetah" }],
      ["3", { cat_id: "5", cat_name: "Leopard" }],
    ];
    
    var tableBody = document.getElementById("wrap");
    
    tableBody.innerHTML = "";
    
    const data = arr.map(a =>
      Object.entries(a[1]).sort(([a], [b]) => a.localeCompare(b))
    );
    
    const headerRow = document.createElement("tr");
    tableBody.appendChild(headerRow);
    for (const [key] of data[0]) {
      const newCell = document.createElement("td");
      newCell.textContent = key;
      headerRow.appendChild(newCell);
    }
    
    for (const datum of data) {
      const newRow = document.createElement("tr");
      tableBody.appendChild(newRow);
      for (const [, value] of datum) {
        const newCell = document.createElement("td");
        newCell.textContent = value;
        newRow.appendChild(newCell);
      }
    }
    <table id="wrap"></table>

    Relevant topics:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search