Search code examples
javascriptarraysstringappendappendchild

Accessing array with string key


I'm generating html elements from a JSON object tableobj and assign them to an array elementArray through the generate() function, this works great, but the problem is when I pass elementArray to the assemble() function I get the following error.

Uncaught TypeError: Cannot read property 'appendChild' of undefined

What I'm looking for is to have the output from assemble() structure the table, which is based of the binding property.

For example: appending <thead> to <table> therefore <thead>'s binding would be 0 since its parent element is elementArray[0] which would be the <table>. This same pattern for <tr> would be 00 since it would be <table> child element 0 which would be <thead>, etc...

//CODE

<script>
var tableobj = [
        {table:{binding:""}},
        {thead:{binding:"0"}},
        {tbody:{binding:"0"}},
        {tr:{binding:"00"}},
        {th:{binding:"000"}},
        {th:{binding:"000"}},
        {th:{binding:"000"}}
];

function init(){
    //GENERATE HTML & BIND PROPERTIES
    var elementArray = generate(tableobj);
    console.log(elementArray);

    //ASSEMBLE THE TABLE --- example: elementArray[0].appendChild(thead) 
    var elementAssembly = assemble(elementArray);

    console.log(elementAssembly);
    console.log(elementAssembly[0]);
    //OUTPUT
    //TABlE->THEAD
    //TABlE->THEAD
    //TABlE->THEAD->TR
    //TABlE->THEAD->TR->TH
    //TABlE->THEAD->TR->TH
    //TABlE->THEAD->TR->TH
}
function assemble(o){   
    o.forEach(function(ele){
        var position = ele.position.replace(/0/g,"[0]");
        var position = ele.position.split('');
        if(ele.position.length > 0){
            //WHERE MY QUESTION LIES....
            var parent = o[position];
            parent.appendChild(ele);
        }
    });
    return o;
};
function generate(o){
    var struct = o.map(function(ele,i){
        var element = document.createElement(Object.keys(ele));
        for(prop in ele){
            var key = Object.keys(ele[prop]);
            key.forEach(function(attr){
                switch(attr){
                    case "binding":
                        Object.defineProperty(element,'position',{
                            value: ele[prop][attr]
                        });
                        break;          
                }
            });         
        }
        return element;
    })
    return struct;
}

//ONLOAD TRIGGER INIT
document.addEventListener('DOMContentLoaded', init);
</script>

Solution

  • Loop over the characters in the binding, getting the child element for each to drill down into the DOM. When you get to the end, append the new element as a child.

    function assemble(o){   
        o.forEach(function(ele){
            var position = ele.position;
            if (position.length == 0) { 
                return;
            }
            var cur = o[0];
            for (var i = 1; i < position.length; i++) {
                cur = cur.children[position[i]];
            }
            cur.appendChild(ele);
        });
    }