10

I'm trying to clone a table row and update the multiple id's to reflect the input fields. I start by doing this and it works:

$(id).clone().attr("id", "newId");

That changes the id of my main table row to the new id. In the table row I have other id's that need to be changed. For example:

<input type="text" id="input_1">

Will be changed to:

<input type="text" id="input_2">

I thought it would be something like this to change the id's:

$(id).clone().attr("id", "newId").("#input_1").attr("id", "input_2");

This doesn't work. How can I fix this so that all of the id's change?

rshivers
  • 147
  • 1
  • 1
  • 11

3 Answers3

29

The program will crash as you have it since you're missing a function call.

Try this instead. Notice the call to find():

$(id).clone().attr("id", "newId").find("#input_1").attr("id", "input_2");

It will probably be better to reference the clone in a variable first.

var $clone = $(id).clone();

$clone.attr("id", "newId").find("#input_1").attr("id", "input_2");
$clone.find("#someElement").attr("id","someElement_2");
$clone.find("#someOtherElement").attr("id","someOtherElement_2");

You can set the ID attributes one at a time for the descendants of your clone if you wish. If there are several, and if you have a consistent pattern for IDs, you will likely be able to do something a little more automated.


EDIT:

Here's an example of automatically updating all the IDs in the $clone.

Please note that this may not work for you, as it assumes that all the IDs end with a number.

var $clone = $(id).clone();    // Create your clone

      // Get the number at the end of the ID, increment it, and replace the old id
$clone.attr('id',$clone.attr('id').replace(/\d+$/, function(str) { return parseInt(str) + 1; }) ); 

     // Find all elements in $clone that have an ID, and iterate using each()
$clone.find('[id]').each(function() { 

     //Perform the same replace as above
    var $th = $(this);
    var newID = $th.attr('id').replace(/\d+$/, function(str) { return parseInt(str) + 1; });
    $th.attr('id', newID);
});
user113716
  • 318,772
  • 63
  • 451
  • 440
  • I have tried using find() before and was able to change one of the attributes, but the other attributes don't change. I was told that is because the next time I use find it thinks that the next element is located within the same id. So if I have 3 id's to change, using find I would change the first, but the others remain untouched. – rshivers Jun 04 '10 at 19:29
  • 2
    @rshivers - That is why I stored the clone in a variable. That stores the entire structure you cloned, so you can do additional `find()` calls against `$clone`. Again, if you have several to update, there's probably a way to do it more quickly than one at a time. – user113716 Jun 04 '10 at 19:32
  • 2
    you can change `$clone.attr('id',$clone.attr('id').replace(/\d+$/, function(str) { return parseInt(str) + 1; }) );` to `$clone.attr('id',function(i, attr){ return attr.replace(/\d+$/, function(str) { return parseInt(str) + 1; } ) });` – azatoth Jun 04 '10 at 20:05
  • @azatoth - Good point. A function can be passed as the second argument to `attr()`. Much cleaner your way. – user113716 Jun 04 '10 at 20:11
  • I don't too much about regular expressions, but this: /\d+$/ fail if all the ID is a whole number, not text + number. Do you know how fix it? – Jose Nobile Jan 07 '15 at 15:15
1

I have found when I do a lot of .clone() stuff it is better to use a class rather than an id attribute. This way you can clone, yet reference it by a known entity (the class), and still get unique via an index into the element group via an .eq()

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
0

I have created a generalised solution. The function below will change ids and names of cloned object. In most cases, you will need the row number so Just add "data-row-id" attribute to the object.

function renameCloneIdsAndNames( objClone ) {

    if( !objClone.attr( 'data-row-id' ) ) {
        console.error( 'Cloned object must have \'data-row-id\' attribute.' );
    }

    if( objClone.attr( 'id' ) ) {
        objClone.attr( 'id', objClone.attr( 'id' ).replace( /\d+$/, function( strId ) { return parseInt( strId ) + 1; } ) );
    }

    objClone.attr( 'data-row-id', objClone.attr( 'data-row-id' ).replace( /\d+$/, function( strId ) { return parseInt( strId ) + 1; } ) );

    objClone.find( '[id]' ).each( function() {

        var strNewId = $( this ).attr( 'id' ).replace( /\d+$/, function( strId ) { return parseInt( strId ) + 1; } );

        $( this ).attr( 'id', strNewId );

        if( $( this ).attr( 'name' ) ) {
            var strNewName  = $( this ).attr( 'name' ).replace( /\[\d+\]/g, function( strName ) {
                strName = strName.replace( /[\[\]']+/g, '' );
                var intNumber = parseInt( strName ) + 1;
                return '[' + intNumber + ']'
            } );
            $( this ).attr( 'name', strNewName );
        }
    });

    return objClone;
}
Piyush Balapure
  • 1,023
  • 9
  • 14