Javascript jquery克隆表单字段并增加id

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8018132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:23:42  来源:igfitidea点击:

jquery clone form fields and increment id

javascriptjquery

提问by puks1978

I have a block of form elements which I would like to clone and increment their ID's using jQuery clone method. I have tried a number of examples but a lot of them only clone a single field.

我有一块表单元素,我想使用 jQuery clone 方法克隆和增加它们的 ID。我尝试了许多示例,但其中很多只克隆了一个字段。

My block is structured as such:

我的块结构如下:

<div id="clonedInput1" class="clonedInput">
  <div>
    <div>
      <label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
      <select class="" name="txtCategory[]" id="category1">
        <option value="">Please select</option>
      </select>
    </div>
   <div>
     <label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
     <select class="" name="txtSubCategory[]" id="subcategory1">
       <option value="">Please select category</option>
     </select>
   </div>
   <div>
     <label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
     <select name="txtSubSubCategory[]" id="subsubcategory1">
       <option value="">Please select sub-category</option>
     </select>
   </div>
</div>

Obviously elements are lined up a lot better but you get the idea.

显然元素排列得更好,但你明白了。

I would like to keep the id structure i.e. category1, subcategory1 etc as I use these to dynamically display select options based on the parent selection so if its possible to have each cloned block like category1/category2/category3 etc that would be great.

我想保留 id 结构,即 category1、subcategory1 等,因为我使用它们来动态显示基于父选择的选择选项,所以如果它可能拥有每个克隆块,如 category1/category2/category3 等,那就太好了。

采纳答案by Milan Jaric

HTML

HTML

<div id="clonedInput1" class="clonedInput">
    <div>
        <label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
        <select class="" name="txtCategory[]" id="category1">
            <option value="">Please select</option>
        </select>
    </div>
    <div>
        <label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
        <select class="" name="txtSubCategory[]" id="subcategory1">
            <option value="">Please select category</option>
        </select>
    </div>
    <div>
        <label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
        <select name="txtSubSubCategory[]" id="subsubcategory1">
            <option value="">Please select sub-category</option>
        </select>
    </div>
    <div class="actions">
        <button class="clone">Clone</button> 
        <button class="remove">Remove</button>
    </div>
</div>

JavaScript - Jquery v1.7 and earlier

JavaScript - Jquery v1.7 及更早版本

var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;

$("button.clone").live("click", function(){
    $(this).parents(".clonedInput").clone()
        .appendTo("body")
        .attr("id", "clonedInput" +  cloneIndex)
        .find("*").each(function() {
            var id = this.id || "";
            var match = id.match(regex) || [];
            if (match.length == 3) {
                this.id = match[1] + (cloneIndex);
            }
    });
    cloneIndex++;
});

There is only one silly part :) .attr("id", "clonedInput" + $(".clonedInput").length)but it works ;)

只有一个愚蠢的部分 :).attr("id", "clonedInput" + $(".clonedInput").length)但它有效 ;)

JAvascript - JQuery recent (supporting .on())

JAvascript - JQuery 最近(支持 .on())

var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;

function clone(){
    $(this).parents(".clonedInput").clone()
        .appendTo("body")
        .attr("id", "clonedInput" +  cloneIndex)
        .find("*")
        .each(function() {
            var id = this.id || "";
            var match = id.match(regex) || [];
            if (match.length == 3) {
                this.id = match[1] + (cloneIndex);
            }
        })
        .on('click', 'button.clone', clone)
        .on('click', 'button.remove', remove);
    cloneIndex++;
}
function remove(){
    $(this).parents(".clonedInput").remove();
}
$("button.clone").on("click", clone);

$("button.remove").on("click", remove);

working example here

这里的工作示例

回答by Craig Burton

Another option would be to use a recursive function:

另一种选择是使用递归函数:

// Accepts an element and a function
function childRecursive(element, func){
    // Applies that function to the given element.
    func(element);
    var children = element.children();
    if (children.length > 0) {
        children.each(function (){
            // Applies that function to all children recursively
            childRecursive($(this), func);
        });
    }
}

Then you can make a function or three for setting the attributes and values of your yet-to-be-cloned form fields:

然后,您可以创建一个或三个函数来设置尚未克隆的表单字段的属性和值:

// Expects format to be xxx-#[-xxxx] (e.g. item-1 or item-1-name)
function getNewAttr(str, newNum){
    // Split on -
    var arr = str.split('-');
    // Change the 1 to wherever the incremented value is in your id
    arr[1] = newNum;
    // Smash it back together and return
    return arr.join('-');
}

// Written with Twitter Bootstrap form field structure in mind
// Checks for id, name, and for attributes.
function setCloneAttr(element, value){
    // Check to see if the element has an id attribute
    if (element.attr('id') !== undefined){
        // If so, increment it
        element.attr('id', getNewAttr(element.attr('id'),value));
    } else { /*If for some reason you want to handle an else, here you go*/ }
    // Do the same with name...
    if(element.attr('name') !== undefined){
        element.attr('name', getNewAttr(element.attr('name'),value));
    } else {}
    // And don't forget to show some love to your labels.
    if (element.attr('for') !== undefined){
        element.attr('for', getNewAttr(element.attr('for'),value));
    } else {}
}

// Sets an element's value to ''
function clearCloneValues(element){
    if (element.attr('value') !== undefined){
        element.val('');
    }
}

Then add some markup:

然后添加一些标记:

<div id="items">
    <input type="hidden" id="itemCounter" name="itemCounter" value="0">
    <div class="item">
        <div class="control-group">
            <label class="control-label" for="item-0-name">Item Name</label>
            <div class="controls">
                <input type="text" name="item-0-name" id="item-0-name" class="input-large">
            </div>
        </div><!-- .control-group-->
        <div class="control-group">
            <label for="item-0-description" class="control-label">Item Description</label>
            <div class="controls">
                <input type="text" name="item-0-description" id="item-0-description" class="input-large">
            </div>
        </div><!-- .control-group-->
    </div><!-- .item -->
</div><!-- #items -->

<input type="button" value="Add Item" id="addItem">

And then all you need is some jQuery goodness to pull it all together:

然后你所需要的只是一些 jQuery 的优点来将它们整合在一起:

$(document).ready(function(){
    $('#addItem').click(function(){
        //increment the value of our counter
        $('#itemCounter').val(Number($('#allergyCounter').val()) + 1);
        //clone the first .item element
        var newItem = $('div.item').first().clone();
        //recursively set our id, name, and for attributes properly
        childRecursive(newItem, 
            // Remember, the recursive function expects to be able to pass in
            // one parameter, the element.
            function(e){
                setCloneAttr(e, $('#itemCounter').val());
        });
        // Clear the values recursively
        childRecursive(newItem, 
            function(e){
                clearCloneValues(e);
            }
        );
        // Finally, add the new div.item to the end
        newItem.appendTo($('#items'));
    });
});

Obviously, you don't necessarily need to use recursion to get everything if you know going in exactly what things you need to clone and change. However, these functions allow you to reuse them for any size of nested structure with as many fields as you want so long as they're all named with the right pattern.

显然,如果您确切知道需要克隆和更改哪些内容,则不一定需要使用递归来获取所有内容。但是,这些函数允许您将它们重用于具有任意数量字段的任何大小的嵌套结构,只要它们都以正确的模式命名。

There's a working jsFiddle here.

有一个工作的jsfiddle这里

回答by Shomz

Clone the main element, strip the id number from it. In the new element replace every instance of that id number in every element id you want incremented with the new id number.

克隆主元素,从中去除 id 号。在新元素中,用新的 id 编号替换您想要增加的每个元素 id 中该 id 编号的每个实例。

Ok, here's a quicky code here.

好吧,这里是一个quicky代码在这里

Basically, this part is the most important:

基本上,这部分是最重要的:

(parseInt(/test(\d+)/.exec($(this).attr('id'))[1], 10)+1

It parses the current id (using RegEx to strip the number from the string) and increases it by 1. In your case instead of 'test', you should put 'clonedInput' and also not only increase the value of the main element id, but the three from the inside as well (category, subcategory and subsubcategory). This should be easy once you have the new id.

它解析当前 id(使用 RegEx 从字符串中去除数字)并将其增加 1。在您的情况下,而不是 'test',您应该放置 'clonedInput' 并且不仅增加主元素 id 的值,但也是从内部开始的三个(类别、子类别和子类别)。一旦你有了新的 id,这应该很容易。

Hope this helps. :)

希望这可以帮助。:)

回答by Jaber Al-Dousari

Add data attribute to the input to get the field name, increment the value with variable.

将数据属性添加到输入以获取字段名称,使用变量增加值。

html :

html :

<td>
   <input type="text" data-origin="field" name="field" id="field" required="" >
  <div role="button" onclick='InsertFormRow($(this).closest("tr"),"tableID","formID");' id="addrow"> + </div>

</td>

and put this javascript function

并把这个javascript函数

var rowNum = 1;

var rowNum = 1;

var InsertFormRow = function(row, ptable, form)
{
    nextrow = $(row).clone(true).insertAfter(row).prev('#' + ptable + ' tbody>tr:last');
    nextrow.attr("id", rowNum);
    nextrow.find("input").each(function() {
        this.name =  $(this).data("origin") + "_" + rowNum;
        this.id =  $(this).data("origin") + "_" + rowNum;
    });
    rowNum++;     
}