jquery clone表单字段和增量id

时间:2011-11-05 04:09:30

标签: javascript jquery

我有一个表单元素块,我想克隆并使用jQuery clone方法增加它们的ID。我尝试过很多例子,但很多例子只能克隆一个字段。

我的块的结构如下:

<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>

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

我想保留id结构,即category1,subcategory1等,因为我使用它们来动态显示基于父选择的选择选项,所以如果它可以让每个克隆块像category1 / category2 / category3等那样会很棒

4 个答案:

答案 0 :(得分:21)

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及更早版本

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++;
});

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

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);

工作示例here

答案 1 :(得分:4)

克隆主元素,从中删除id号。 在新元素中,在每个元素id中替换该id号的每个实例,并使用新的id号进行递增。

好的,这是一个快速的代码here

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

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

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

希望这会有所帮助。 :)

答案 2 :(得分:4)

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

// 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);
        });
    }
}

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

// 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('');
    }
}

然后添加一些标记:

<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">

然后你需要的只是一些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'));
    });
});

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

有一个有效的jsFiddle here

答案 3 :(得分:0)

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

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>

并把这个javascript函数

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++;     
}