Skip to content Skip to sidebar Skip to footer

Is There A Way To Dynamically Create Nested Divs Onclick?

I'm attempting to create a page where the user is able to customize the form to their needs by adding in extra divs or nested divs (as many layers deep as they'd like). Within each

Solution 1:

Here is a complete solution for you keep in mind that if you need to bind extra events on your produced inputs and buttons you ll have to do it inside the functions addNode or addSub as i did for the click event on the buttons.

Working example : https://jsfiddle.net/r70wqav7/

var counter = 1;
functionaddNode(element) {
	counter++;
  var new_entry="Entry "+counter+"<br><input type='text' name='myInputs'><br>";
  element.insertAdjacentHTML("beforebegin",new_entry);
}
functionaddSub(element) {
	counter++;
	var new_sub_entry="<div class='block'>"
  								+"Entry "+counter+"<br><input type='text' name='myInputs'><br>"
                  +"<div class='buttons'>"
                  +"<input class='add_sub_button' type='button' value='add nested'>"
                  +"<input class='add_button' type='button' value='Add another text input' >"
                  +"</div>"
                  +"</div><br />"
                  +"</div>";
  element.insertAdjacentHTML("beforebegin",new_sub_entry); 
  var blocks=element.parentNode.getElementsByClassName("block");
  blocks[blocks.length-1].getElementsByClassName("add_sub_button")[0].addEventListener("click",function(){
  	addSub(this.parentNode);
  });
  blocks[blocks.length-1].getElementsByClassName("add_button")[0].addEventListener("click",function(){
  	addNode(this.parentNode);
  });
}

var buttons=document.getElementsByClassName("add_button");
for(i=0;i<buttons.length;i++){
	buttons[i].addEventListener("click",function(){
  		addNode(this.parentNode);
  });
}
var nested_buttons=document.getElementsByClassName("add_sub_button");
for(i=0;i<buttons.length;i++){
	nested_buttons[i].addEventListener("click",function(){
  		addSub(this.parentNode);
  });
}
div.block{
  padding:5px;
  border:2px solid #000;
}
<formclass="form"method="POST"><divclass="block">
        Entry 1<br><inputtype="text"name="myInputs"><br><divclass="buttons"><inputclass="add_sub_button"type="button"value="add nested"><inputclass="add_button"type="button"value="Add another text input" ></div></div><br /><inputtype="submit"value = "answer"multiple="multiple"/></form>

EDITED : There was an error binding the click event on nested items updated to work properly

Solution 2:

Here's another worked example which makes use of the concepts I mentioned in an earlier comment. I've moved the Add-Item button outside the form and altered the method used to determine the text for each new item added. Rather than keep a counter, I count the number of existing items in the document and increment it, using this as as the n in the string "Entry n"

I should have added(appended) the sub-item before the button that creates new ones, but was lazy and just called appendChild on the button after the other new element was added - the end result is the same, but it's less efficient and will cause slower performance/shorter battery life.

I was going to use the .cloneNode method of the .dynamicInput div, when clicking "Add new item", however this will copy all subitems of the chosen target and we still need to call addEventListener for the button anyway, so I've opted to simply create each input-item added with the "Add new item" button instead.

<!doctype html><html><head><script>
"use strict";
functionbyId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
functionallByClass(className,parent){return (parent == undefined ? document : parent).getElementsByClassName(className);}
functionallByTag(tagName,parent){return (parent == undefined ? document : parent).getElementsByTagName(tagName);}
functionnewEl(tag){returndocument.createElement(tag);}
functionnewTxt(txt){returndocument.createTextNode(txt);}

window.addEventListener('load', onDocLoaded, false);

functiononDocLoaded(evt)
{
    byId('addNewInputBtn').addEventListener('click', myAddNewItem, false);
    var subItemBtn = document.querySelectorAll('.dynamicInput button')[0];
    subItemBtn.addEventListener('click', myAddSubItem, false);
}

functionmakeNewItem(titleStr)
{
    var div = newEl('div');
    div.className = 'dynamicInput';

    var heading = newEl('h3');
    heading.innerText = titleStr;
    div.appendChild(heading);

    var input = newEl('input');
    div.appendChild(input);

    var btn = newEl('button');
    btn.innerText = 'Add sub-items';
    btn.addEventListener('click', myAddSubItem, false);
    div.appendChild(btn);

    return div;
}


functionmyAddNewItem(evt)
{
    var numAlreadyExisting = allByClass('dynamicInput').length;             // count number of divs with className = dynamicInputvar newNum = numAlreadyExisting + 1;
    var newInputPanel = makeNewItem('Entry ' + newNum);
    byId('myForm').appendChild(newInputPanel);
    returnfalse;
}

functionmyAddSubItem(evt)
{
    evt.preventDefault();                                                   // stops this button causing the form to be submittedvar clickedBtn = this;
    var inputDiv = clickedBtn.parentNode;
    var newInput = newEl('input');
    inputDiv.appendChild(newInput);
    inputDiv.appendChild(clickedBtn);
}

</script></head><body><formid='myForm'><divclass='dynamicInput'><h3>Entry 1</h3><inputtype='text'/><button>Add sub-item</button></div></form><buttonid='addNewInputBtn'>Add new item</button></body></html>

Post a Comment for "Is There A Way To Dynamically Create Nested Divs Onclick?"