jquery克隆表单字段并增加id

IT技术 javascript jquery
2021-02-01 15:21:12

我有一块表单元素,我想使用 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个回答

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

这里的工作示例

大家好,再次感谢您提供的精彩代码。它的工作效率为 99.9%。有一个愚蠢的点(我认为你正在考虑 Milan Jaric),如果我克隆 3 次,并删除中间的(数字 2),我有 element1 和 element3。然后当我再次克隆时,我有第二个 element3,因为 .length 认为只有 3 个。我想我可以找到一种方法来循环访问可用元素并分配下一个可用数字,但如果您有任何建议也会很棒。
2021-03-15 15:21:12
嗨,干得好!当有一个选项时,我将您的脚本调整为隐藏按钮删除。参见jsfiddle.net/effectlabweb/8p1e6ug5
2021-03-17 15:21:12
很抱歉成为一个真正的屁股痛。是否可以为克隆的元素添加删除按钮/链接。每个 1 个,所以说如果我创建了 10 个克隆,我可以删除第五个吗?
2021-03-27 15:21:12
谢谢@Shomz,我将添加您的代码以完成示例 aboe(只是为了不引人注目)
2021-04-02 15:21:12
上面/^(.+?)(\d+)$/i;的正则表达式不能处理超过 9 个元素,你需要使用非贪婪匹配:(@MilanJaric,你的正则表达式也不能工作,因为它只挑出最后一个整数
2021-04-13 15:21:12

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

// 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这里

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

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

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

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

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

希望这可以帮助。:)

谁能拒绝提供代码 ;) 正如我所提到的,我已经尝试了很多方法,但都没有运气,所以是的,请...那太好了。
2021-03-28 15:21:12
好了,希望我说得更清楚了。您还可以检查您获得的新 ID 号是否已被使用(例如,如果您克隆元素 #1,然后是 #2,然后是 #1 或 #2 - 您将获得新的 id = 3,自从我们克隆了 #2 以来,#3 已经存在,所以我们需要下一个增量),等等……如果您需要更多帮助,请告诉我。:)
2021-04-10 15:21:12

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

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