Reputation: 359
I'm trying to convert the nested JSON data into a HTML table, but it kept throwing error.
I am not sure where I did wrong. Maybe something's wrong with the method of accessing the array inside the object?
It kept throwing this error:
"Cannot set property 'innerHTML' of null"
Below is the code I wrote :
function DonutTable(array){
//create a table element
var table = document.createElement("table");
//create header columns
var col = Object.keys(array[0]); //array of keys
//write keys onto the header cell
var tr = table.insertRow(-1);
col.forEach(function(key){
var th = document.createElement("th");
th.textContent = key;
tr.appendChild(th);
});
//create rows to hold the rest of the data
array.forEach(function(obj){
//for each obj in the main array, create a row
var data_row = table.insertRow(-1);
//for each header in the col array, populate data
col.forEach(function(key){
var tabCell = data_row.insertCell(-1);
if (key==="batters"){
//grab the value of batters and access value of batter
obj["batters"]["batter"].forEach(function(e){
//for each e in batter, create a div element
var div = document.createElement("div");
//write on the div
div.textContent = e.type + "(" + e.id + ")";
tabCell.appendChild(div); })
}
if (Array.isArray(obj[key])){ //check if a value of a key is an array
obj[key].forEach(function(topping){
//for each obj in topping, get id and type
var div = document.createElement("div");
div.textContent = topping.type + "(" + topping.id + ")";
tabCell.appendChild(div);
})
}
else{
tabCell.textContent = obj[key];
}
})
})
var divContainer = document.getElementById("showTable");
divContainer.innerHTML = "";
divContainer.appendChild(table);
}
var donut = [
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
]
DonutTable(donut);
<html>
<head>
<title>HTML Donut Table from JSON</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<input type="button" value="Generate a table" onclick="DonutTable()">
<div id="showTable"></div>
</body>
</html>
Upvotes: 6
Views: 2761
Reputation: 13334
This is your exact code that I just split into JS and HTML parts.
It works on initial run since donut
array is explicitly passed to DonutTable()
function. It does not work on button click since your HTML calls DonutTable()
with no parameters.
function DonutTable(array){
//create a table element
var table = document.createElement("table");
//create header columns
var col = Object.keys(array[0]); //array of keys
//write keys onto the header cell
var tr = table.insertRow(-1);
col.forEach(function(key){
var th = document.createElement("th");
th.textContent = key;
tr.appendChild(th);
});
//create rows to hold the rest of the data
array.forEach(function(obj){
//for each obj in the main array, create a row
var data_row = table.insertRow(-1);
//for each header in the col array, populate data
col.forEach(function(key){
var tabCell = data_row.insertCell(-1);
if (key==="batters"){
//grab the value of batters and access value of batter
obj["batters"]["batter"].forEach(function(e){
//for each e in batter, create a div element
var div = document.createElement("div");
//write on the div
div.textContent = e["type"] + "(" + e["id"] + ")";
tabCell.appendChild(div); })
}
else if (Array.isArray(obj[key])){ //check if a value of a key is an array
obj[key].forEach(function(topping){
//for each obj in topping, get id and type
var div = document.createElement("div");
div.textContent = topping.type + "(" + topping.id + ")";
tabCell.appendChild(div);
})
}
else{
tabCell.textContent = obj[key];
}
})
})
var divContainer = document.getElementById("showTable");
divContainer.innerHTML = "";
divContainer.appendChild(table);
}
var donut = [
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
]
DonutTable(donut);
<html>
<head>
<title>HTML Donut Table from JSON</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<input type="button" value="Generate a table" onclick="DonutTable()">
<div id="showTable"></div>
</body>
</html>
Upvotes: 2
Reputation: 617
In Chrome, set a breakpoint right after you declare your divContainer. Based on the code, it looks like divContainer is null because you are running the JavaScript before the HTML in on the page. Either move the JS into a document.ready type function or move the script section to below the HTML.
Upvotes: 2