I am looking for an effective way to either clone/rename or re-create address fields to offer ability to submit multiple addresses on the same page. So with form example like this:
<div id="addresses">
<div class="address">
<input type="text" name="address[0].street">
<input type="text" name="address[0].city">
<input type="text" name="address[0].zip">
<input type="text" name="address[0].state">
</div>
</div>
<a href="" id="add_address">Add address form</a>
From what I can understand there are two options to do that:
-
Recreate the form field by field and increment the index which is kind of verbose:
var index = $(".address").length; $('<`input`>').attr({ name: 'address[' + index + '].street', type: 'text' }).appendTo(...); $('<`input`>').attr({ name: 'address[' + index + '].city', type: 'text' }).appendTo(...); $('<`input`>').attr({ name: 'address[' + index + '].zip', type: 'text' }).appendTo(...); $('<`input`>').attr({ name: 'address[' + index + '].state', type: 'text' }).appendTo(...); -
Clone Existing layer and replace the name in the clone:
$("div.address").clone().appendTo($("#addresses"));
Which one do you recommend using in terms of being more efficient and if its #2 can you please suggest how I would go about search and replacing all occurrences of [0] with [1] ([n]). Thank you.
In theory, the simplest way would be to clone then change name:
However:
a. jQuery’s
clone()is a really nasty piece of work. On IE, it serialises the nodes to HTML, processes the HTML string with regex (!) to remove its bodge-job internal ID attributes and then asks the browser to re-parse it. This is one of my least favourite parts of jQuery: it’s highly error-prone, loses some information, and is slow (not that speed matters for the quite small job you seem to be doing here).The browser’s native
cloneNode(true)method is much better, but you can’t really use it if you’re doing jQuery stuff because it will copy jQuery’s internal ids, potentially confusing its scripting. Ugh. What a mess.b. When you change an input’s name, whether that’s by
input.nameas here or usingattr()as in your example, there are issues in IE<=7.In particular, though it will submit the inputs with the correct control name, they won’t be indexed under the right name in the
form.elementsHTMLCollection (or onformitself, though you shouldn’t use that anyway). This isn’t necessarily a problem if you are selecting inputs based on IDs or jQuery selectors rather than the old-school HTMLCollection interface. Worse is that radio buttons, if you use any, won’t be properly name-grouped.If this is a concern for you I’m afraid using
innerHTML/html()to create the div, as in pst’s answer, is your only option. (You can always combine the two, creating using HTML then changing the other attributes and text content usingtext(),attr(),val()etc. to avoid the usual HTML-escaping problems when you go around sticking text strings into HTML.)