6

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>
1
  • If this is your actual code, then you may attempt to access HTML element before your page is fully rendered. Commented Dec 22, 2017 at 17:06

2 Answers 2

2

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.

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

1 Comment

THank you. My table shows now. But the batters section didn't display correctly. It shows [Object, Object], which means there's something wrong with the forEach loop I use to access the array inside the object .
2

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>

3 Comments

Thank you. Mine works now too. But something's wrong with the "batters" column. I accessed the array inside the object, used forEach to loop through each obj in the array and wrote it out, but it still showed : [object Object]. Do you know why?
Thank you but if I don't use the else statement , then other columns won't be filled in
Then you need to use if ,,, else if ... else .. construct. See the update.

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.