Michael
Michael

Reputation: 2284

Using jQuery to Clone Multiple Form Elements Within Separate Divs

I am using the following script to clone a div with form elements inside; however, it currently adding sequential numbers (1, 2, 3) to the container div id correctly, but then is adding a "name2" and "name3" to the sub-divs in the clone, instead of to the actual form elements.

Example of problem:

<div class="clonedInput" id="container1">
    <div>First Name:
        <input type="text" id="first_name1" name="first_name1">
    </div>
    <div>Last Name:
        <input type="text" id="last_name1" name="last_name1">
    </div>
    <div>Phone:
        <input type="text" id="phone1" name="phone1">
    </div>
</div>

<div class="clonedInput" id="container2">
    <div id="name2" name="name2">First Name:
        <input type="text" id="first_name1" name="first_name1">
    </div>
    <div>Last Name:
        <input type="text" id="last_name1" name="last_name1">
    </div>
    <div>Phone:
        <input type="text" id="phone1" name="phone1">
    </div>
</div>

<div class="clonedInput" id="container3">
    <div id="name3" name="name3">First Name:
        <input type="text" id="first_name1" name="first_name1">
    </div>
    <div>Last Name:
        <input type="text" id="last_name1" name="last_name1">
    </div>
    <div>Phone:
        <input type="text" id="phone1" name="phone1">
    </div>
</div>

Full code:

<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
jQuery( function ( $ ) {
    $( '#btnAdd' ).click( function() {
        var num = $( '.clonedInput' ).length;      // how many "duplicatable" input fields we currently have
        var newNum  = new Number( num + 1 );        // the numeric ID of the new input field being added
        var newElem = $( '#container' + num ).clone().attr( 'id', 'container' + newNum );

        newElem.children( ':first' ).attr( 'id', 'name' + newNum ).attr( 'name', 'name' + newNum );
        $( '#container' + num ).after( newElem );
        $( '#btnDel' ).attr( 'disabled', false );
        if ( newNum == 25 )
            $( '#btnAdd' ).attr( 'disabled', 'disabled' );
    });

    $( '#btnDel' ).click( function() {
        var num = $( '.clonedInput' ).length;      // how many "duplicatable" input fields we currently have
        $( '#container' + num ).remove();              // remove the last element
        $( '#btnAdd' ).attr( 'disabled', false );  // enable the "add" button

        // if only one element remains, disable the "remove" button
        if ( num-1 == 1 )
            $( '#btnDel' ).attr( 'disabled', 'disabled' );
    });

    $( '#btnDel' ).attr( 'disabled', 'disabled' );
});
        </script>
</head>

<body>
<form id="myForm">
    <div id="container1" class="clonedInput"> 
        <div>
        First Name:
        <input type="text" name="first_name1" id="first_name1">
        </div>
        <div>
        Last Name:
        <input type="text" name="last_name1" id="last_name1">
        </div>
        <div>
        Phone:
        <input type="text" name="phone1" id="phone1">
        </div>
    </div>
    <div>
        <input type="button" id="btnAdd" value="add another name" />
        <input type="button" id="btnDel" value="remove name" />
    </div>
</form>
</body>
</html>

Upvotes: 2

Views: 6098

Answers (4)

Metabolic
Metabolic

Reputation: 2904

Though not a solution to the OP question, I found Jquery Form Clone Plugin to be quite helpful. Its has everything preset, index, nested forms, controls and even callbacks like beforeAdd, after add etc. I mentioned it because when searching for a jQuery's solution, I ended up here. So I thought it might help others searching for jQuery's solution for cloning forms

Upvotes: 0

Abdul Rahman A Samad
Abdul Rahman A Samad

Reputation: 1152

Here's what I do: if you have multiple layers of div, tables (like me), you have to change the code provided by Brian Glaz from newElem.children to newElem.find. Here is his fiddle: http://jsfiddle.net/B7bgN/10/

All I did was change one word. From children to find. (Children will only traverse one level while find will get descendants of each element.

http://jsfiddle.net/the7th/sSS3c/1/

$(document).ready(function () {
                                    var newNum = 1;
                                    cloneMe = function (el) {
                                        var newElem = el.clone().attr('class', 'firstrow' + newNum).insertAfter(".firstrow0");

                                        newElem.find('input').each(function (index, elem) {
                                            $(elem).attr('id', $(elem).attr('id') + newNum).attr('name', $(elem).attr('name') + newNum);
                                        });
                                        if (newNum == 2) {
                                            $("#cloneb").hide();
                                        };
                                        newNum++;
                                    };
                                });

Upvotes: 1

Brian Glaz
Brian Glaz

Reputation: 15666

The problem is this line here:

newElem.children( ':first' ).attr( 'id', 'name' + newNum ).attr( 'name', 'name' + newNum );

Only the first child of each newElem is being selected, which is why only the first input element is being changed. What you want to do is select ALL the children that are input elements. Try this:

newElement.children('input').attr('id',$(this).attr('id') + newNum).attr('name',$(this).attr('name') + newNum);

Upvotes: 1

Raynos
Raynos

Reputation: 169383

var cloneEl = (function () {
    var counter = 1;

    return function cloneEl(id) {
        var el = document.getElementById("container");
        var clone = el.cloneNode(true);

        clone.id = el.id+counter;
        [].forEach.call(clone.children, function (node, key) {
             var oldNode = el.children[key];
             node.id = oldNode.id+counter;
             node.name = oldNode.id+counter;
        });

        counter++;
        return clone;
    };
})(); 

Live Example

Upvotes: 1

Related Questions