3
\$\begingroup\$

I have HTML code like this :

<a class="btn btn-default" href="#" id="addTxt">Add Text</a>
<div id="nF">
    <div class="form-inline">
        <div class="input-group">
            <div class="input-group-addon"><i class="fa fa-text-width"></i>
            </div>
            <input class="form-control" id="project_components_attributes_32943600_name" name="project[components_attributes][32943600][name]" type="text">
            <span class="input-group-btn">
              <input id="project_components_attributes_32943600__destroy" name="project[components_attributes][32943600][_destroy]" type="hidden" value="false">
              <a class="btn btn-default" data-selector="removeField" href="#">
                <i class="fa fa-remove"></i>
              </a>
            </span>
        </div>
    </div>
</div>

If I click link "Add Text", It will clone div with class form-inline and append to div#nF and then replacing all attribute of input tag in form-inline (id and name) with new value from new date and time.

For Illustration :

id => project_components_attributes_32943600_name => replace "32943600" with new value

name => project[components_attributes][32943600][_destroy] => replace "32943600" with new value

And this javascript :

$(document).ready(function(){
    $('#addTxt').click(function(){
        var time = new Date().getTime();
        var $target = $('#nF').find('div.form-inline:first');
        $target.clone().appendTo('#nF');
        $target.find('input').each(function(){           
           $(this).val('');
           var tID = $(this).attr("id").split(/_/);
           var re = new RegExp(tID[3],"g");
           var newID = $(this).attr('id').replace(re, time);
           var newName = $(this).attr('name').replace(re, time);
           $(this).attr('id', newID);
           $(this).attr('name', newName);
        });
    });
});

Live Demo : http://jsfiddle.net/gjj8mzya/

Is there any way to clone element and replace attributes?

\$\endgroup\$
2
\$\begingroup\$

The current code does essentially this:

  1. Clone the dirtied first item and append to the end
  2. Modify the dirtied first item to make it clean again

It would be better to use a clean prototype / template from which you can easily create clean new instances. Then the operations can become:

  1. Move the dirtied first item to the end
  2. Recreate the first item from the clean template

The first approach is not so good, because:

  • Cloning is always a suspicious operation. For example, you have to make sure that:
    • all fields correctly copied
    • no references accidentally leaked
    • deep objects correctly deep-copied: although this is not a concern in this specific example, but I'm adding it anyway as a reminder of general concerns about the concept of cloning
  • Reseting an object to a clean state is always a suspicious operation. For example, you have to make sure that:
    • all fields are correctly reset: often duplicating the same logic that must exist (explicitly or implicitly) in the initializer / constructor

The new approach doesn't have any of these tricky issues. It's conceptually much cleaner, with much fewer hidden traps and bugs waiting to happen.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.