jquery clone form fields and increment id

前端 未结 4 2134
抹茶落季
抹茶落季 2020-11-27 03:37

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 clo

相关标签:
4条回答
  • 2020-11-27 04:13

    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

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

    JAvascript - JQuery recent (supporting .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

    0 讨论(0)
  • 2020-11-27 04:19

    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:

    $(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.

    0 讨论(0)
  • 2020-11-27 04:20

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

    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

    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++;     
    }
    
    0 讨论(0)
  • 2020-11-27 04:28

    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.

    Ok, here's a quicky code here.

    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.

    Hope this helps. :)

    0 讨论(0)
提交回复
热议问题