jaread83
jaread83

Reputation: 49

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>

Upvotes: 0

Views: 104

Answers (1)

angel.bonev
angel.bonev

Reputation: 2232

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>

Upvotes: 1

Related Questions