How to deal with cloning or dynamically loading new form elements (like radio buttons) in Internet Explorer (IE) using jQuery

It's a horrendously long blog title, I know, but I wanted to mash in all the keywords I was looking for when trying to find a solution to this very sticky problem so that other folks running into the same issue can spend the next six hours doing something more productive.

jQuery makes grabbing one group of elements from a page, duplicating them and adding them somewhere else really easy. You just use a combination of clone() and something like append(), as in the following:

$('#surrounding_div').clone().appendTo('#some_other_div);

The problem with dynamically adding form elements in IE

Woot! So easy! Right, until you start goofing with forms and IE (Internet Explorer) (appropriate sound). The problem is that IE doesn't allow you to manipulate the 'name' attribute in the DOM directly. So, something like this won't work:

$('#form_element').clone().attr('name', 'new-name').appendTo('#my-form);

If you do that with a radio button, the interface will tell you that there's a problem, because since the new radio button has the same name as the original one, only one can be selected. Bugger!

Luckily, the solution is clear, but it took forever to figure it out. Instead of adjusting the name attribute directly with something like attr(), you need to edit it manually in a block of html and then add that html to the page. So, something like this would work:

$('#form_element').parent().html().
replace(/orignal_name/, 'new_name').appendTo('#my-form');

There's a couple of key points here:

  1. Because we're getting the html using $.html(), we need to move up the DOM to grab the element surrounding the element we wish to add using $.parent(), then we can grab the html using $.html().
  2. I'm using the javascript replace() function to pass a regex pattern and replacement text to the html.

What about dynamically cloning groups of inputs with jQuery?

In my particular use case, I was grabbing a set of form elements and adding them this way. There were a couple of challenges, which was that I couldn't use $.parent() to get the outer element, and the other was that the names of the form elements were being set dynamically. I learned a couple of tricks to help with this:

Use the regex modifier /g to replace all insteances of a pattern. So, when doing replace(), if I needed to replace ALL instances instead of just one, it would look like this:

replace(/original_name/g, 'new_name')

Because I couldn't use $.parent(), in the end I had to wrap an element around the html using simple contatination, like so:

var newHTML = '<div>' + $('#element').html() + '</div>';

I hope that helps you, it was sure a bugger to figure out.



Comments

Thank you SO much for writing about this. What a lifesaver to know what was going on under the hood.

As a heads up, I made what I believe to be an improvement upon your solution. It takes more code, but it is more precise in the replacement since the parent may contain a bunch of HTML that you don't want to muck with and accidentally replace something important. Here's what we did.

var myElement = $('#element');
if ($.browser.msie) {
myElement.replaceWith(myElement.outerHTML.replace(/original_name/g, 'new_name'));
} else {
myElement.attr('name', myElement.attr('name').replace(/original_name/, 'new_name'));
}

Note that this works because IE respects outerHTML, but other browsers (notably Firefox) do not. So I use the best way whenever possible, but when it comes to IE, we restrict the replacement to outerHTML which contains the string representation of the element.

This worked fine for us.

Thanks again for the help!

it makes me wonder why jQuery doesn't do this by default...

Brilliant blog post - I was experiencing very similar behaviour and needed to understand what IE was doing with radio button names. Thank you!

Life saving post! I was pulling my hair out, and it was awesome to end up on your blog. Thanks for sharing.

Thanks for the post!

This seems to be what I'm needing to do with a form I'm working on. However, its for a registration site that will ideally allow the user to add as many people to the form as they need to. So the user may add just one, but they also may add 5 or 10 (although not likely that many). So I'm thinking I need to somehow add a variable that counts up each time the user adds a set of inputs and then append that number to the name attribute.

Am I thinking correctly here, or is there a quick and easy way to account for unique names across an indefinite amount of duplications?

Thanks a ton!!