2

I'm trying to create an HTML table from a JSON file which values can include nested lists.

Example:

{
     "entry 1":[
         ["text1", "text2", "text3"],
         ["text4", "text5", "text6"],
         ["text7", "text8", "text9"]
    ],
    "entry 2": "N/A",
    "entry 3": [
         ["text1", "text2", "text3"],
         ["text4", "text5", "text6"]
    ],
    "entry 4": [
         ["text1", "text2"],
         ["text3", "text4"]
    ]
}

My goal is to create an HTML table with a predefined header for the two columns:

  • header_title_1
  • header_title_2

That will never change, and the table should look like this:

table_example

Thanks for your help !

2
  • 1
    Stack overflow is not a free code writing service; have you tried anything so far? Commented Apr 12, 2021 at 8:08
  • Object.keys(obj) gives keys which can be iterated over to get desired table HTML Commented Apr 12, 2021 at 8:15

2 Answers 2

2

Using the for...in iterator on the object to get the key. I created a row for each property, then a cell for the key and value. Then if the value isn't an array, like the entry2 key, we make it an array to iterate through the elements.

Creating a new row for each element in the array and creating a new cell for the items in the array. If it is an array, the value would be converted to a string separated by the comma ',' or it would be set just as it is.

Then we append the elements to the body of the table.

const tbody = document.getElementById('table').tBodies[0];
const obj = {"entry 1":[["text1","text2","text3"],["text4","text5","text6"],["text7","text8","text9"]],"entry 2":"N/A","entry 3":[["text1","text2","text3"],["text4","text5","text6"]],"entry 4":[["text1","text2"],["text3","text4"]]};

function createTable(obj) {
  tbody.innerHTML = ''; // To reset the table
  
  for (const key in obj) {
    if (!obj.hasOwnProperty(key)) continue;
    const value = Array.isArray(obj[key]) ? obj[key] : [obj[key]];
    const row = document.createElement('tr');
    const key_cell = Object.assign(document.createElement('td'), {
      innerText: key
    });
    const value_column = Object.assign(document.createElement('td'), {
      innerText: value.splice(0, 1)[0]
    });

    row.append(...[key_cell, value_column]);
    tbody.append(row);

    value.forEach(val => {
      const inner_row = document.createElement('tr');
      const empty_key_cell = document.createElement('td');
      const value_cell = Object.assign(document.createElement('td'), {
        innerText: val
      });
      inner_row.append(...[empty_key_cell, value_cell]);
      tbody.append(inner_row);
    });
  }
}

createTable(obj);
<table id="table" border="1" width="100%">
  <thead>
    <td>header_title_1</td>
    <td>header_title_2</td>
  </thead>
  <tbody></tbody>
</table>

Sign up to request clarification or add additional context in comments.

7 Comments

thanks a lot, it works perfectly! If I want to add a horizontal line in between each row, should this be added in the JS script or the html ?
If you mean the way it looks like in the picture you linked, I've edited my code for that...
Is that what you meant?
one last question, my page starts with filter buttons to select the JSON file to load before creating the table, should your script include a 'id = table' somewhere to make it dynamic ?
The first table loads just fine, but when I try to press the btton to load another JSON, I get the following error message in the console: "Unable to preventDefault inside passive event listener due to target being treated as passive"
|
1

Or, in a very short way, you could do the following instead:

const obj=
{"entry 1":[["text1","text2","text3"],["text4","text5","text6"],["text7","text8","text9"]],
 "entry 2":"N/A",
 "entry 3":[["text1","text2","text3"],["text4","text5","text6"]],
 "entry 4":[["text1","text2"],["text3","text4"]]};
 
document.querySelector("#table tbody").innerHTML=
Object.entries(obj).map(([k,v])=>
   "<tr><td>"+k+"</td><td>"
  +(Array.isArray(v)?v:[[v]]).join("<hr>")
  +"</td></tr>").join("\n")
td>hr {margin:0px}
td {vertical-align:top}
<table id="table" border="1" width="100%">
  <thead>
    <th>header_title_1</th>
    <th>header_title_2</th>
  </thead>
  <tbody></tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.