简体   繁体   中英

Render a tree object as HTML elements

I am having some difficulties with this problem. I want to render some html elements given a tree structure. For example this javascript tree object:

let htmlTree = {
    id: "a",
    children: [{
        id: "b",
        children: []
    }, {
        id: "c",
        children: [{
            id: "d",
            children: []
        }]
    }]
};

Should output a string like this:

<a>
    <b>
    </b>
    <c>
        <d></d>
    </c>
</a>

What I tried doing was a breadth first traversal (iterative) of the tree object but was having some issues actually knowing when to apply the close tag of the element for the nested cases. Any help is appreciated, i've been stumped on this all day :(

I know you already have an answer for this, but I thought this was valid to add to the discussion. You can have the Javascript dom functions do the heavy lifting for you. This might be valuable in more complex scenarios.

function create_node(obj){
    var node = document.createElement(obj.id);
    for (var i in obj.children) {
        node.appendChild(create_node(obj.children[i]));
    }
    return node;
}
console.log(create_node({id:'root',children:[htmlTree]}).innerHTML);

JSFiddle: http://jsfiddle.net/trex005/8gxe7z3b/

note : to get the full HTML, I wrapped it in a parent node to use innerHTML since there is no cross browser way of getting the outterHTML.

This'll make the string without line breaks...and I'm using var instead of let for more compatibility

var outputStr='';
function checkChildren(parentObj){
    outputStr+='<'+parentObj.id+'>';
    if(parentObj.children.length>0)
        parentObj.children.forEach(checkChildren);
    outputStr+='</'+parentObj.id+'>';
}
checkChildren(htmlTree);

And it is easy to modify if you do need it to have the line breaks. Here's a working jsfiddle

I spent a lot of time doing something like this and in my efforts I built a really efficient framework which uses a object-orient approach, little more complex but it allows for very quick development, with an API like interface.

  1. Declare a JSON object in a very simple syntax as shown in the code
  2. Declare a object-specific create method (Form.prototype.create) and specify how to build the object.
  3. Then simply call the Build()-function and pass the JSON object as the argument. example --- Build(signin)

//CODE

    <!DOCTYPE html>
    <html>
    <head>
    <script>
    //SIMPLE JSON SYNTAX
    var signin = [
        {"container":{"element": "aside", "attributes": {"id":"overlay","class":"overlay1","onclick":"Destroy(event);"}}},
        {"form":{"element": "form", "attributes": {"id":"form"}}},
        {"msg":{"element": "mark", "attributes": {"id":"form-msg"}}},
        {"ipt1":{"element": "input", "attributes": {"type":"email","placeholder":"email","name":"email"}}},
        {"ipt2":{"element": "input", "attributes": {"type":"password","placeholder":"password","name":"password"}}},
        {"ipt3":{"element": "input", "attributes": {"type":"button","value":"Sign In","class":"form-btn btn-blue", "data-url":"/core/signin.php","onclick":"Submit(this);"}}},
        {"ipt4":{"element": "input", "attributes": {"type":"button","value":"Account Recovery","class":"form-btn btn-black","data-form":"recover","onclick":"Build(recover)"}}}
    ];

    //MAIN BUILD FUNCTION
    function Build(obj){
        //CREATE NEW FORM OBJECT WITH DYNAMIC PROP AND VALUES
        var form = Form.new(obj);

        //CREATE HTML ELEMENTS AND APPEND ITS ATTRIBUTES 
        form.assemble();

        //DEFINE HOW YOU WANT THE OBJECT TO BE ASSEMBLED
        form.create();
    }

   //DYNAMIC FORM CONSTRUCTOR
    function Form(){
        for(var i=0; i < arguments.length; i++){
            var key = Object.keys(arguments[i]);
            this[key] = arguments[i][key];
        }   
    }
   //FORM OBJECT CONSTRUCTOR METHOD (CREATE)
    Form.prototype.create = function(){
        var inpts = Object.keys(this).splice(3);
        var container = document.body.appendChild(this.container);
        var form = container.appendChild(this.form);
        container.appendChild(this.msg);
        for(i=0; i < inpts.length; i++){
            form.appendChild(this[inpts[i]]);
        }           
    }
    //GLOBAL FUNCTION METHOD (NEW)
    Function.prototype.new = function (args) {
        var Fake = Object.create(this.prototype);
        this.apply(Fake, args);
        return Fake;
    };
    //GLOBAL OBJECT METHOD (ASSEMBLE)
    Object.prototype.assemble = function(){
        for(key in this){
            if(this.hasOwnProperty(key)){
                var element = document.createElement(this[key].element);
                var attributes = this[key].attributes;
                for(prop in attributes){
                    if(attributes.hasOwnProperty(prop)){
                        element.setAttribute(prop, attributes[prop]);
                        this[key] = element;
                    }
                }   
            }
        }       
    }
    </script>
    </head>
    <body></body>
    </html>

Try this

var treeRendrer = function(treeObj,parent){
      if(treeObj && treeObj.hasOwnProperty("id")){
         parent.appendChild(document.createElement(treeObj["id"]))
      }
      if(treeObj && treeObj.hasOwnProperty("children")){
         treeObj.children.forEach(function(childObj){
            treeRendrer(childObj, parent.firstChild)
         });
      } 
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM