简体   繁体   English

有没有办法动态创建嵌套的divs onclick?

[英]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). 我正在尝试创建一个页面,用户可以通过添加额外的div或嵌套的div(根据他们喜欢的多层深度)来自定义表单。 Within each div I'd like to have text input and a button which adds another div on the same level and a button that nests a div within it. 在每个div中,我想要文本输入和一个按钮,它在同一级别上添加另一个div和一个嵌入div的按钮。 Both divs should again have a text input and a button which does the same thing. 两个div应该再次具有文本输入和按钮,它们执行相同的操作。

However I've gotten a bit stuck. 但是我有点卡住了。 When I attempt to create a nested div I always end up adding it at the very bottom instead of inside its parent. 当我尝试创建一个嵌套的div时,我总是最后将它添加到底部而不是在其父级内部。

<html>
    <script type="text/javascript">
        var counter = 1;
        function addNode() {
            var newDiv = document.createElement('div');
            counter++;
            newDiv.innerHTML = "Entry " + counter + " <br><input type='text' name='myInputs'>";
            document.getElementById("dynamicInput").appendChild(newDiv);
            var newButton = document.createElement('button');
            newButton.type = "button";
            newButton.onclick = addSub;

            document.getElementById("dynamicInput").appendChild(newButton);
        }
        function addSub() {
            var newDiv = document.createElement('div');
            counter++;
            newDiv.innerHTML = "Entry " + counter + " <br><input type='text' name='myInputs' style='margin:10px'>";
            document.getElementById("subInput").appendChild(newDiv);
        }
    </script>
    <form class="form" method="POST">
        <div id="dynamicInput" name="dynamicInput" multiple="multiple">
            Entry 1<br><input type="text" name="myInputs">
            <div id="subInput" name="subInput" multiple="multiple">
                <input type="button" value="add nested" onClick="addSub();">
            </div>
        </div>
        <input type="button" value="Add another text input" onClick="addNode();" >
        <input type="submit" value = "answer" multiple="multiple"/>

    </form>
</html>

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. 这是一个完整的解决方案,请记住,如果您需要在生成的输入和按钮上绑定额外的事件,您必须在函数addNode或addSub中执行它,就像我对按钮上的click事件所做的那样。

Working example : https://jsfiddle.net/r70wqav7/ 工作示例: https//jsfiddle.net/r70wqav7/

 var counter = 1; function addNode(element) { counter++; var new_entry="Entry "+counter+"<br><input type='text' name='myInputs'><br>"; element.insertAdjacentHTML("beforebegin",new_entry); } function addSub(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; } 
 <form class="form" method="POST"> <div class="block"> Entry 1<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 /> <input type="submit" value = "answer" multiple="multiple"/> </form> 

EDITED : There was an error binding the click event on nested items updated to work properly 已编辑:绑定更新的嵌套项上的click事件以使其正常工作时出错

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. 我已经在表单外移动了Add-Item按钮,并更改了用于确定添加的每个新项目的文本的方法。 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" 我不是保留一个计数器,而是计算文档中现有项目的数量并将其递增,使用它作为字符串“Entry n”中的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. 我应该在创建新的按钮之前添加(附加)子项,但是在添加了另一个新元素之后在按钮上调用了appendChild - 最终结果是相同的,但效率较低并且会导致性能降低/电池寿命缩短。

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. 当我点击“添加新项目”时,我将使用.dynamicInput div的.cloneNode方法,但是这将复制所选目标的所有子项,我们仍然需要为该按钮调用addEventListener ,所以我选择了简单地创建添加了“添加新项”按钮的每个输入项。

<!doctype html>
<html>
<head>
<script>
"use strict";
function byId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
function allByClass(className,parent){return (parent == undefined ? document : parent).getElementsByClassName(className);}
function allByTag(tagName,parent){return (parent == undefined ? document : parent).getElementsByTagName(tagName);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}

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

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

function makeNewItem(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;
}


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

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

</script>
</head>
<body>
    <form id='myForm'>
        <div class='dynamicInput'>
         <h3>Entry 1</h3>
         <input type='text'/><button>Add sub-item</button>
        </div>
    </form>
    <button id='addNewInputBtn'>Add new item</button>
</body>
</html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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