jquery clone form fields and increment id

前端 未结 4 2205
抹茶落季
抹茶落季 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: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:

    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.

提交回复
热议问题