简体   繁体   中英

Recursion in javascript to build HTML with children that have a single parent element

I have a json object that I am looping over and building html blocks with each object. I have got this to work fine so far but I am having issues with the child items not being in its own parent container. I also don't want the top level items to be contained in a parent container.

Any help and advice would be greatly appreciated.

 // test json data var jsonTest = { "myJson": [ { "type": "link", "navigationIndex": 0, "formData": { "label": "link", "url": "https://www.google.com" }, "childItems": [ { "type": "column", "navigationIndex": 0, "formData": { "label": "column 1" }, "childItems": [] }, { "type": "column", "navigationIndex": 1, "formData": { "label": "column 2" }, "childItems": [] }, { "type": "column", "navigationIndex": 2, "formData": { "label": "column 3" }, "childItems": [] }, { "type": "column", "navigationIndex": 3, "formData": { "label": "column 4", }, "childItems": [] }] }] }; // main build function function buildFromJson() { var jsonData = jsonTest.myJson; appendDom($(".root"), jsonData); } // html templates function getLinkContainer(type, label, url) { var element = ` <div class="element" data-item-type="${type}"> <a href="${url}">${label}</a> </div> `; return element; }; function getColumnContainer(type, label) { var element = ` <div class="element" data-item-type="${type}"> ${label} </div> `; return element; } // recursion to get all data function appendDom(container, jsonData) { for (var i = 0; i < jsonData.length; i++) { var $divParent = $("<div class='parent'></div>"); if(jsonData[i].type == "link") { var url = jsonData[i].formData.url; var label = jsonData[i].formData.label; var type = jsonData[i].type; $divParent.append(getLinkContainer(type, label, url)); } else if(jsonData[i].type == "column") { var label = jsonData[i].formData.label; var type = jsonData[i].type; $divParent.append(getColumnContainer(type, label)); } // get the children if (jsonData[i].childItems) { appendDom($divParent, jsonData[i].childItems); } container.append($divParent); } } // build it! buildFromJson(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="root"> </div> 

jsfiddle provided here: https://jsfiddle.net/y4qdknb1/1/

Results:

<div class="root">
    <div class="parent">
        <div class="element" data-item-type="link">
            <a href="https://www.google.com">link</a>
        </div>
        <div class="parent">
            <div class="element" data-item-type="column">
                column 1
            </div>
        </div>
        <div class="parent">
            <div class="element" data-item-type="column">
                column 2
            </div>
        </div>
        <div class="parent">
            <div class="element" data-item-type="column">
                column 3
            </div>
        </div>
        <div class="parent">
            <div class="element" data-item-type="column">
                column 4
            </div>
        </div>
    </div>
</div>

What I actually want:

<div class="root">
    <div class="element" data-item-type="link">
        <a href="https://www.google.com">link</a>
        <div class="parent">
            <div class="element" data-item-type="column">
                column 1
            </div>
            <div class="element" data-item-type="column">
                column 2
            </div>
            <div class="element" data-item-type="column">
                column 3
            </div>
            <div class="element" data-item-type="column">
                column 4
            </div>
        </div>
    </div>
</div>

You need to use the container not the $divParent

AFTER QUESTION UPDATE

Create new element and always append it to current container , after that check if there is any children and append them to that element

 var jsonTest = { "myJson": [ { "type": "link", "navigationIndex": 0, "formData": { "label": "link", "url": "https://www.google.com" }, "childItems": [ { "type": "column", "navigationIndex": 0, "formData": { "label": "column 1" }, "childItems": [] }, { "type": "column", "navigationIndex": 1, "formData": { "label": "column 2" }, "childItems": [] }, { "type": "column", "navigationIndex": 2, "formData": { "label": "column 3" }, "childItems": [] }, { "type": "column", "navigationIndex": 3, "formData": { "label": "column 4", }, "childItems": [] }] }] }; // main build function function buildFromJson() { var jsonData = jsonTest.myJson; appendDom($(".root"), jsonData); } // html templates function getLinkContainer(type, label, url) { var element = ` <div class="element" data-item-type="${type}"> <a href="${url}">${label}</a> </div> `; return element; } ; function getColumnContainer(type, label) { var element = ` <div class="element" data-item-type="${type}"> ${label} </div> `; return element; } // recursion to get all data function appendDom(container, jsonData) { for (var i = 0; i < jsonData.length; i++) { if (jsonData[i].type == "link") { var url = jsonData[i].formData.url; var label = jsonData[i].formData.label; var type = jsonData[i].type; var element = $(getLinkContainer(type, label, url)); } else if (jsonData[i].type == "column") { var label = jsonData[i].formData.label; var type = jsonData[i].type; var element = $(getColumnContainer(type, label)); } container.append(element); // get the children if (jsonData[i].childItems) { var $divParent = $("<div class='parent'></div>"); $(element).append($divParent); appendDom($divParent, jsonData[i].childItems); } } } // build it! buildFromJson(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="root"> </div> 

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