jQuery – Dynamically Adding Form Elements
You know the situation. You have a form with ‘x’ number of text inputs. Eventually, you realize ‘x’ may not be enough for all users. But in the interest of keeping the page clean, you don’t want to arbitrarily continue to add these elements.
What you really want to do is show a minimal amount initially, and then give the user the option of adding as many more (within reason) as that particular user might need. You might go about doing that by creating 100 fields and setting their CSS display attribute to “none”, while adding a slick JavaScript function to allow the user to display as many as they need. And that would work, but…
Why create any DOM elements that aren’t going to be used? Wouldn’t it be better to dynamically create an element and add it to the DOM as the user needs it? (Hopefully you’re nodding in affirmation) Great! Let’s do it with jQuery.
First, you’ll want to see it in action. I’ve put together a quick demo for you to check out. The rules of the demo are simple. You can add up to 5 names, and you must have at least one. Take a look and c’mon back so we can walk through the code.
Let’s take a look at the code first, and then break it down. As with previous entries, you can copy and paste this code onto your own machine and run it, since it points to Google for the jQuery core files. Also be aware that the jQuery code is much leaner than what you see. Almost half of the lines of code are comments for your benefit.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(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
// create the new element via clone(), and manipulate it's ID using newNum value
var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);
// manipulate the name/id values of the input inside the new element
newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum);
// insert the new element after the last "duplicatable" input field
$('#input' + num).after(newElem);
// enable the "remove" button
$('#btnDel').attr('disabled','');
// business rule: you can only add 5 names
if (newNum == 5)
$('#btnAdd').attr('disabled','disabled');
});
$('#btnDel').click(function() {
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
$('#input' + num).remove(); // remove the last element
// enable the "add" button
$('#btnAdd').attr('disabled','');
// 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="input1" style="margin-bottom:4px;" class="clonedInput">
Name: <input type="text" name="name1" id="name1" />
</div>
<div>
<input type="button" id="btnAdd" value="add another name" />
<input type="button" id="btnDel" value="remove name" />
</div>
</form>
</body>
</html>
The Markup
Let’s look at what’s going on, starting with the form itself:
<form id="myForm"> <div id="input1" style="margin-bottom:4px;" class="clonedInput"> Name: <input type="text" name="name1" id="name1" /> </div> <div> <input type="button" id="btnAdd" value="add another name" /> <input type="button" id="btnDel" value="remove name" /> </div> </form>
Very straightforward markup. A single form with an “id” attribute. The form contains a div holding a text input and some label text. The div is assigned a class of “clonedInput”. This is important. The name can be whatever you choose, but the fact that there is a particular class assigned to this div will be used in our jQuery code.
Next up is another div that holds 2 button elements, each with a unique id attribute. As you might have guessed, on click, one will add a new form element, and the other will remove a form element.
That’s it for our markup. And therein lies the true beauty of jQuery. Our markup is clean and pristine. No need to litter it with hidden elements that we may not even need.
jQuery – The First Step
Moving to the jQuery code itself. Starting off very basic, the first thing we’re going to do is disable the “remove name” button. Since the page initially renders with only one name field, we don’t want to let the user remove that.
$(document).ready(function() {
$('#btnDel').attr('disabled','disabled');
}
At it’s most basic, jQuery adheres to the principle of “find something, do something”. Right now, we’re finding the element with the id “btnDel”, and what we’re doing with it is setting it’s “disabled” attribute to “disabled”.
jQuery – Adding a New Form Element
Next we’re going to want to handle the click event for the “btnAdd” button:
$(document).ready(function() {
$('#btnDel').attr('disabled','disabled');
$('#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
// create the new element via clone(), and manipulate it's ID using newNum value
var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);
// manipulate the name/id values of the input inside the new element
newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum);
// insert the new element after the last "duplicatable" input field
$('#input' + num).after(newElem);
// enable the "remove" button
$('#btnDel').attr('disabled','');
// business rule: you can only add 5 names
if (newNum == 5)
$('#btnAdd').attr('disabled','disabled');
});
}
Still using the “find something, do something” principle, but this time, once we find the element (in this case, the element with the id “btnAdd”), we’re going to listen for a specific event (in this case, the click event), before we do something (in this case, create a new element and append it to the DOM).
var num = $('.clonedInput').length;
var newNum = new Number(num + 1);
var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);
First we’re going to set a few variables:
- Using a jQuery selector, we’re going to look for all elements with the class of “clonedInput” (remember this was the class assigned to the div that held the actual form element). jQuery returns an array of matching elements. We need to know how many there currently are, so we access the array’s length property.
- The variable newNum is going to refer to the next element… the one we’re going to create. So we increment the previous variable (num) by one.
- The variable newElem is a reference to a DOM element that we’re going to create using jQuery’s built in clone() method. Again, using a selector and the “find something, do something” principle, we’re going to find the last of the clone-able inputs. As we only have one to start, its id (and name) attribute is “input1″. We concatenate the variable num (created in item 1 above) to access that specific element. We clone() it, and then using method chaining, set its id attribute to be “input2″ (subsequent elements would be “input3″, “input4″, and “input5″).
Now that we’ve got our new <div> (complete with a unique ID), we need to manipulate the “name” and “id” attributes of the <input> within.
newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum);
Remember that “newElem” refers to our newly created DOM element. It’s a div that contains an input. The input is the first “child” element of the div, so it can be referenced via:
newElem.children(':first');
Next, we want to set the “id” attribute and “name” attribute. Recall that with the first text input, these attributes had the same value (“name1″). Using the “newNum” variable that was set above, we can easily set the “id” and “name” attributes of our new element to “name2″.
Again, we’re using method chaining. The script block above could have been written as:
newElem.children(':first').attr('id', 'name' + newNum);
newElem.children(':first').attr('name', 'name' + newNum);
But that’s not quite as efficient as method chaining, and also a little more verbose. Chained methods do not have to be on the same line, and for the sake of legibility can be written as:
newElem.children(':first')
.attr('id', 'name' + newNum)
.attr('name', 'name' + newNum);
Now that we have our new element all set up, we need to insert it into the DOM. As of yet, it’s not part of the page, it’s just a jQuery variable.
$('#input' + num).after(newElem);
Remember that “num” refers to the current number of clone-able elements. If there’s only one element on the page, num equals 1. Using a jQuery selector, we reference the last input, and using the appropriately named jQuery method after(), insert our new element (newElem) into the DOM.
Just 2 more steps and we’re done with adding an element.
Because we just added a new element, we know for a fact that we have more than one. So we can now enable the “remove name” button. The first line of jQuery that we wrote today disabled it by setting the “disabled” attribute to “disabled”. We just undo that by setting the value to an empty string.
$('#btnDel').attr('disabled','');
Finally, we need to enforce our business rule of ensuring a maximum of 5 elements.
if (newNum == 5)
$('#btnAdd').attr('disabled','disabled');
Hopefully, you see what happened there. If the value of newNum (the variable representing the newly added DOM element) is 5, disable the “add another name” button. This is identical to disabling the “remove name” button, except for the selector.
jQuery – Removing a Form Element
Good news. We’re halfway there. We can now add (up to 5) elements dynamically. But we need to allow the user to remove any elements that they added as well.
$('#btnDel').click(function() {
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
$('#input' + num).remove(); // remove the last element
// enable the "add" button
$('#btnAdd').attr('disabled','');
// if only one element remains, disable the "remove" button
if (num-1 == 1)
$('#btnDel').attr('disabled','disabled');
});
To add a new element, we started out by listening for a click event on the element with the ID “btnAdd”. Now, we’re going to listen for a click event on the element with the ID “btnDel”. Also similar to above, we want to start out by getting the total number of “clonedInput” elements:
var num = $('.clonedInput').length;
And now that we know how many there are, we can safely remove the last one. jQuery makes this easy by providing a built-in remove() method:
$('#input' + num).remove();
Since we’ve just removed an element, we’re guaranteed to have fewer than the 5 specified as the maximum. We can therefore safely make sure the “add another name” button is enabled:
$('#btnAdd').attr('disabled','');
Finally (yes, I know it’s been a long time coming), we need to disable the “remove name” button if only one element remains:
if (num-1 == 1)
$('#btnDel').attr('disabled','disabled');
Putting it all Together (One More Time)
That’s it. If you’ve stuck with me this far, more power to you. I know it might seem complex, but if you take the time to really look at each line you’ll see how straightforward it is. This entry ran a bit longer than I had anticipated, but I wanted to make sure to explain what was happening on a line-by-line basis. In reality, without comments “cluttering” the script, we’re talking about under 20 lines of jQuery. Here it is again, the entire page, without comments. Hopefully that will help illustrate that it really is a pretty concise way of handling the need to dynamically add or remove elements from the DOM. Take another look and see if it isn’t more clear than it was when you first looked at it above.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#btnAdd').click(function() {
var num = $('.clonedInput').length;
var newNum = new Number(num + 1);
var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);
newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum);
$('#input' + num).after(newElem);
$('#btnDel').attr('disabled','');
if (newNum == 5)
$('#btnAdd').attr('disabled','disabled');
});
$('#btnDel').click(function() {
var num = $('.clonedInput').length;
$('#input' + num).remove();
$('#btnAdd').attr('disabled','');
if (num-1 == 1)
$('#btnDel').attr('disabled','disabled');
});
$('#btnDel').attr('disabled','disabled');
});
</script>
</head>
<body>
<form id="myForm">
<div id="input1" style="margin-bottom:4px;" class="clonedInput">
Name: <input type="text" name="name1" id="name1" />
</div>
<div>
<input type="button" id="btnAdd" value="add another name" />
<input type="button" id="btnDel" value="remove name" />
</div>
</form>
</body>
</html>
While I do think it’s concise, I also recognize that it might be intimidating when you’re new to the jQuery library. If you have questions or comments, please don’t hesitate to post them, and I’ll do my best to answer.
jQuery concepts used:
153 comments | 152,973 views


marc esher
Charlie,
this seems like one of those posts that a lot of people would look at and no one would comment on because they’re starry eyed by your sheer brilliance. Consequently, I want to congratulate you on a fine post.
Nice code formatting, too! I bet that was a pain to put into your blog, and for your additional attention to such formatting you should be commended.
Student
You tutorial is very good & i implement it straight away. But i am facing problem as i need to add Serial noeach row of input fields being added i tried head over heals but i havnt got lucky so far. It would be great if you can show how to add a serial before each input fields so that i can have a form like
1. Name …………………..
2. Name………………….
3 Name………………….
I not good with jQuery & have looked for several hours for the solution with out any success.
Dana
I would do this with an Ordered List in the HTML, and an in the cloned Div:
Charlie
Hi Dana:
Just FYI, you can surround code blocks in
[ code ][ /code ](without the spaces), so I went ahead and updated your comment with the proper markup.Muneeb
I definitely am thankful to the author of article about writing and explaining the jquery stuff here.
Thumbs up….
Charlie Griefer
@Marc – heh. thanks
This entry ended up being longer than I had expected, and I was just worried that it was information overload. Not much point in taking the time to compose a blog entry if folks aren’t able to absorb it (and thus learn from it) in one sitting.
The code formatting is SyntaxHighlighter (http://alexgorbatchev.com/wiki/SyntaxHighlighter). If anyone deserves kudos, it’s Alex. He did a great job on it.
TJ Downes
Bookmarked. Good stuff Charlie, thanks!
Mark Mandel
Is it wrong that I do it this way with jquery (written inline, so typos will exist):
<cfsavecontent variable="formElem">
{label}: <input type="text" name="{id}" id="{id}" />
</cfsavecontent>
<script type="text/javascript">
formElemHTML = "#JSStringFormat(formElem)#";
newElementHTML = formElemHTML.replace(/{label}/ig, "My fancy new label");
newElementHTML = newElementHTML.replace(/{id}/ig, counter++);
$("#parentElement").append(newElementHTML);
</script>
That’s a really lazy showing of it, but you get the gist ;o)
I just like writing the template in HTML in cfsavecontent, so I don’t have to build the DOM node by node.
Whatcha think?
Charlie Griefer
@Mark – Yeah, it’s wrong
It’s actually a pretty cool approach, and one that I’d not thought of. Always interesting to see a different means to the same end. I’m not sure it’s all that much simpler… your 4 lines are equivalent to 5 of mine (so yeah OK, 1 line simpler)
GT
Hey there Charlie,
Thanks for this – it provides the foundation for what I’m after. I’m trying to write a ‘stock picker’ where users can choose their own criteria and then hit ‘send’ and get the data back.
I just spent a couple of hours looking for a way to construct a ‘multiple filter’ on a mySQL database with an interface similar to the e-mail filter function in Thunderbird (or the data filters in Excel or OpenOffice Calc).. simple as pie in design, but getting the functionality to dynamically add new filters was a pain until I found your site.
Goes to show how important search terms are: I started with "multiple form filters mySQL" and wound up finding the right universe by the time I got to "jquery dynamically add remove elements"; took me eight searches before I even got onto the right track.
Cheers
GT
Phil Webb
Charlie,
First off, amazing code! Very clever. I would like to add multiple text fields in each div. It displays and works correctly but when I submit it only one of the fields comes through correctly. Say the fields are ?size? and ?color? I get size1, color1, color2, color3, etc.. In other words, the code to rename the name and id only works on one of the fields. You used newElem.children(‘:first’) to access the single field in your example. I assumed I could loop through all the children and use a similar line for each child. The length of the children is only 1, which is confusing. I figured there would be one child for each text box. Any ideas? Thanks!
Phil
Charlie Griefer
@Phil – If your div contains 2 text inputs, there should be 2 children elements. For example, if I have this:
<div id="myDiv">
<input type="text" name="text1" id="text1" />
<input type="text" name="text2" id="text2" />
</div>
Then the following jQuery alerts the value ’2′:
$(function(){
alert($(‘#myDiv’).children().length);
});
Against the same markup, the following jQuery properly alerts "text1" and then "text2":
$(function(){
$(‘#myDiv’).children().each(function() {
alert($(this).attr(‘id’));
})
});
Perhaps you’re not looping properly?
Phil Webb
Thanks Charlie. I am up and running. I had used children.length instead of children().length to get the length of the children.
Out of curiosity, is there a way to directly access one of the children without using the .each loop or :first? Something like $(‘#myDiv’).children(‘foo’).attr(‘id’).
Charlie Griefer
@Phil – Lots of ways
For example…
$(‘#myDiv’).children().eq(0) <– first child
$(‘#myDiv’).children().eq(1) <– second child
I’d suggest looking at:
http://docs.jquery.com/Selectors
http://docs.jquery.com/Traversing
and some really good stuff at:
http://www.learningjquery.com/2006/11/how-to-get-anything-you-want-part-1
http://www.learningjquery.com/2006/12/how-to-get-anything-you-want-part-2
If you have a specific situation you’re trying to address and need some help, let me know.
Steve Snyder
Ok. So I understand how this works and I am trying to incorporate it with another script. So far it duplicates the input elements perfectly but I have a script that shows additional information when a Select Option is selected. When you "add another", it works fine however the script that shows the additional info only works on the first. Is there anyway that I can send the number of cloned Div to that script?
Here’s the code:
<script language="JavaScript" type="text/javascript">
function getElementsByClass( searchClass, domNode, tagNames) {
if (domNode == null) domNode = document;
if (tagNames == null) tagNames = ‘*’;
var el = new Array();
var tags = domNode.getElementsByTagName(tagNames);
var tcl = " "+searchClass+" ";
for(i=0,j=0; i<tags.length; i++) {
var test = " " + tags[i].className + " ";
if (test.indexOf(tcl) != -1)
el[j++] = tags[i];
}
return el;
}
function showHide(id)
{
// hide every element with class ‘tab’
var tabs = getElementsByClass(‘hideit’);
for(i=0; i<tabs.length; i++)
tabs[i].style.display = ‘none’;
// hide every element with class ‘tab’
document.getElementById(id).style.display=’block’;
// show element with given tabname
}
</SCRIPT>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(‘#btnAdd’).click(function() {
var num = $(‘.clonedInput’).length;
var newNum = new Number(num + 1);
var newElem = $(‘#input’ + num).clone().attr(‘id’, ‘input’ + newNum);
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
$(‘#input’ + num).after(newElem);
$(‘#btnDel’).attr(‘disabled’,”);
if (newNum == 10)
$(‘#btnAdd’).attr(‘disabled’,'disabled’);
});
$(‘#btnDel’).click(function() {
var num = $(‘.clonedInput’).length;
$(‘#input’ + num).remove();
$(‘#btnAdd’).attr(‘disabled’,”);
if (num-1 == 1)
$(‘#btnDel’).attr(‘disabled’,'disabled’);
});
$(‘#btnDel’).attr(‘disabled’,'disabled’);
});
</script>
</head>
<body>
<form id="myForm">
<div id="input1" style="margin-bottom:4px;" class="clonedInput">
<fieldset>
<legend>Fabric Type:</legend>
Select Fabric: <select name="fabrictype1">
<option value="Booth Buddy" onClick="showHide(‘boothbuddy1′);" />Booth Buddy</option>
<option value="PopUp (LP Stretch)" onClick="showHide(‘popup1′);" />PopUp (LP Stretch)</option>
<option value="Retractable Banner Stand" onClick="showHide(‘bannerstand1′);">Retractable Banner Stand</option>
<option value="Hanging Sign" onClick="showHide(‘hangingsign1′);">Hanging Sign</option>
<option value="Delta Fabric" onClick="showHide(‘deltafabric1′);">Delta Fabric</option>
<option value="Table Throw" onClick="showHide(‘tablethrow1′);">Table Throw</option>
<option value="Table Skirt" onClick="showHide(‘tableskirt1′);">Table Skirt</option>
<option value="Companion" onClick="showHide(‘companion1′);">Companion</option>
<option value="Companion 2" onClick="showHide(‘companion21′);">Companion 2</option>
<option value="Stretch Case Wrap" onClick="showHide(‘casewrap1′);">Stretch Case Wrap</option>
<option value="Pole Pocket Banner" onClick="showHide(‘polepocket1′);">Pole Pocket Banner</option>
<option value="Custom" onClick="showHide(‘custom1′);">Custom …</option>
</select>
<div class="hideit 1" id="boothbuddy1" style="display:none;">
<b>PolySuede – </b><span id="smalltext">Hemmed Edges, Pole pocket top and bottom, Grommets top and bottom.</span>
</div>
<div class="hideit 1" id="popup1" style="display:none;">
<b>PolySuede – </b><span id="smalltext">Hemmed Edges, 2" Velcro sewn to edge.</span>
</div>
<div class="hideit 1" id="bannerstand1" style="display:none;">
<b>Sierra, X-banner, L-Banner – </b><span id="smalltext">Janus – Hotknife Sides, Finished top and bottom.</span>
</div>
<div class="hideit 1" id="hangingsign1" style="display:none;">
<b>Softknit – </b><span id="smalltext">Zipper(s) along top edges, Hemmed where needed</span>
</div>
<div class="hideit 1" id="deltafabric1" style="display:none;">
<b>PolySuede – </b><span id="smalltext">Sewn silicone</span>
<b>Tripoly – </b><span id="smalltext">Sewn silicone</span>
</div>
<div class="hideit 1" id="tablethrow1" style="display:none;">
<b>PolySuede – </b><span id="smalltext">Hemmed around edges</span>
<b>Softknit – </b><span id="smalltext">Hemmed around edges</span>
</div>
<div class="hideit 1" id="polepocket1" style="display:none;">
<b>Material – </b><span id="smalltext">PolySuede</span>
<b>Finishing – </b><span id="smalltext">Hemmed edges, pole pockets</span>
<b>Specify – </b><span id="smalltext">Pole pocket size or pole diameter</span>
</div>
<div class="hideit 1" id="custom1" style="display:none;">
<b>Material – </b><input type="text" name="fabcmaterial1" /><br />
<b>Finishing – </b><input type="text" name="fabcfinishing1" /><br />
<b>Finished – </b><input type="text" name="fabcfinished1" /><br />
<b>Live Area – </b><input type="text" name="fabclivearea1" /><br />
<b>Other Information:</b><br />
<textarea name="fabccomments1" cols="70"></textarea>
</div>
</fieldset></div>
<div>
<input type="button" id="btnAdd" value="add another name" />
<input type="button" id="btnDel" value="remove name" />
</div>
</form>
J
Great post. You broke it down to the perfect level. Just what I was looking for.
Thanks!
Simon Griffee
Excellent stuff?thank you Charlie!
One suggestion: Please considering removing the double-dashes in the URL for this post (?jQuery–Dynamically?).
The double-dashes seem to break an HTML page when the link to this post is placed inside an HTML comment. I discovered this when crediting you for using the above!
Cheers,
Simon
Charlie Griefer
@Steve Snyder – You’ll need to understand what the code is doing, and use appropriate naming conventions. All elements that are duplicated have a "1" after the element name/id. After using jQuery’s clone(), you’d need to increment all of those to "2" (then to "3", etc). I worked up some sample code that I can post later on.
@Simon – Heh. I suppose I can modify that thru the alias in BlogCFC’s administrator. In the meantime, how about tinyurl? Either way, thanks for the credit
Dan Fish
Great howto. It’s really helped a project of mine. I’m still kind of new to this, so I’m probably being dumb, but I’ll like to put the remove button next to the added field so users have the option of removing that added line specifically. Any pointers?
Alexia
Hi!
Very gooood work! But i have a question for u: How can i use your code and change also THE LABEL of the text box to Name2, Name3 etc…?
Any ideas?
Thank you
Sunny
Thank you so much for this post, I’ve been looking for a good explanation of dynamic forms with jQuery. I’m so relieved to find just what I needed that I’m going to give a way-too-personal explanation. I’m at a job where web-programming was suddenly thrown onto me even though I’m an electrical engineer. After a month of stressfully trying to work with php I’m somewhat up and running, actually kind of like web-programming. Anyway thanks for making my life easier! I’ll buy you a beer if we ever meet
Snyder
Hey, first of all thanks for the great tutorial. don’t know if you check this post anymore, but was wondering how you would validate the newly created input fields just using php. I tried but when I submit and it fails my checks, it loses all the new input elements and I have to re-type everything. I guess I’m asking how you would make the newly created input fields "sticky". I know I could just do jQuery validation, but I want it to be functional without javascript in case someone doesn’t have it enabled. food for thought. Thanks!
Ivan Ribakov
Hi, thanks for the code – i modified it a bit to suit my needs, but faced one problem – the inputs that are created dynamically are not being submitted. This happens only in Firefox, but does work in Chrome and even IE.
Here’s HTML:
<div id=\"input1\" class=\"clonedInput\">
<label for=\"answer1\" class=\"answer_label\">Answer</label>
<input type=\"text\" name=\"answer1\" id=\"answer1\" class=\"answer\" />
<label for=\"answer1pt\" class=\"point_label\">Points</label>
<input type=\"text\" name=\"answer1pt\" id=\"answer1pt\" class=\"points\" size=\"2\"/>
</div>";
/*Copied from PHP code that why quotes are backslashed*/
And your modified JavaScript code:
$(‘#btnAddAnswer’).click(function() {
var num = $(‘.clonedInput’).length;
var newNum = num + 1;
var newElem = $(‘#input’ + num).clone().attr(‘id’, ‘input’ + newNum);
newElem.find(".answer_label").attr(‘for’, ‘answer’ + newNum);
newElem.find(".answer").attr(‘id’, ‘answer’ + newNum).attr(‘name’, ‘answer’ + newNum).attr(‘value’, ”);
newElem.find(".point_label").attr(‘for’, ‘answer’ + newNum + ‘pt’);
newElem.find(".points").attr(‘id’, ‘answer’ + newNum + ‘pt’).attr(‘name’, ‘answer’ + newNum + ‘pt’).attr(‘value’, ”);
$(‘#input’ + num).after(newElem);
$(‘#btnDelAnswer’).attr(‘disabled’,”);
if (newNum == 5)
$(‘#btnAddAnswer’).attr(‘disabled’,'disabled’);
});
Any ideas what i’m doing wrong or what the trouble might be?
P.S. dont know if it is still relevant, but you can get certain child of an element using this construction:
newElem.find(":nth-child(1)").attr(‘for’, ‘answer’ + newNum);
Thanks in advance!
Kliphten
Great post. Question: I used this for multiple image uploads but when I post the data, it doesn’t go through? Anybody know if I need to do anything to get this to work? I’ve tried adding a text field dynamically as well and it didn’t work either. Any help would be great!
Gerald
Great Post,
I want to know If is it posible to validate the new input generated?
doforumda
This is a good post i like it but i have some problem with it. i modified your code according to my needs. it is working fine as far as adding new form elements is concern. but the problem arise when i try to submit my data to server side scripting. how can i get all the data that are added to all the dynamic fields in this script. let me give my code to you
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(‘#btnAdd’).click(function() {
var num = $(‘.clonedInput’).length;
var newNum = new Number(num + 1);
var newElem = $(‘#input’ + num).clone().attr(‘id’, ‘input’ + newNum);
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
$(‘#input’ + num).after(newElem);
});
});
</script>
<style>
#myForm div {
font-size:14px;
margin-bottom: 10px;
clear: left;
}
#myForm label {
width: 125px;
display: block;
font-size:14px;
font-weight: bold;
color: #999;
float: left;
}
#btnAdd {
margin-left:130px;
}
</style>
</head>
<body>
<form id="myForm" method="post" action="process.php">
<div>
<label>First Name: </label><input type="text" name="fname" id="fname"><br>
</div>
<div>
<label>Last Name: </label><input type="text" name="lname" id="lname"><br>
</div>
<div id="input1" class="clonedInput">
<label>IM Screen Names:</label>
<input type="text" name="name1" id="name1" />
<select name="screenname1" id="screenname1">
<option value="AIM" selected="selected">AIM</option>
<option value="gtalk">Google Talk</option>
<option value="skype">Skype</option>
<option value="windows live">Windows Live</option>
<option value="yahoo">Yahoo</option>
</select><br />
</div>
<div>
<a href="#" id="btnAdd">Add another</a>
</div>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
let me give you server side script too so it will be better to understand it. please modify where am i making mistake
<?php
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$name1 = $_POST['name1'];
$screenname1 = $_POST['screenname1'];
echo $fname."<br>";
echo $lname."<br>";
echo $name1."<br>";
echo $screenname1."<br>";
?>
Davidmoreen
Absolutely perfect. This post could have not of gotten anymore in depth, as well it saved me a few bucks from having to buy an application that incorporated this and viewing the source code. Very good post and I’ll be coming back soon to se what other great things you have going on on this website!
George
Just to say thanks. Just what I needed. I had a label in front of my input so had to change your line 16 from targeting:
children(‘:first’)
to:
children(‘.myinput’)
If anyone is confused I did this so that the attribute manipulation is done on the child element with the class of "myinput" instead of the first child.
Ajith
Thanks Charlie.Excellent Article.After wasting my long 2 hours atlast i reached in front you.Very very thanks
Ryan
I was looking for a quick and easy solution to this and this helped me amazingly – however, I needed to add multiple childen (e.g. name1, email1, phone1) and didn’t want to loop.
I ended up using;
newElem.children(‘:nth-child(2)’).attr(‘id… etc.
newElem.children(‘:nth-child(3)’).attr(‘id… etc.
As the number of fields will never change and I didn’t want to loop this seemed to offer a quick and easy solution. Unless I’m missing something more complex about this.
Thanks again for posting.
Jennifer
This seems like a great solution. I tried implementing but I am having one small issue. I am cloning several fields including drop down lists. For the text boxes. The textboxes post as a comma delimited list and the dropdowns just post one selected value. It seems like they all have the same name even though they are unique. Since so many people seem to have gotten this working, I am wondering if there is something I am missing.
john
i’m probably too late for this, but it’s worth a try.
this is wonderful, but i can’t seem to get it to work within my existing page
when i just extract the code, it works fine in my envron, but when i put it into my page, both buttons are grayed out
why?
john
to answer my own question, i removed all the other javascript on the page and it worked
hence a conflict with the other junk i had
thanks for the script!
mommaroodles
WOW, cant believe my luck! this seems to be just the script I’m looking for, however, I am a real newbie to Jquery and am having difficulty getting the script exactly to work as I’d like it.
As in doforumda’s comment posted on 2/17/10 10:08 PM – what I am trying to do is instead of just adding the one field is add all three fields. Fields being the following
Boy/Girl – radio button
Childs name – text field
Childs birthdate – text field
Can this be done and if so some advice on how to do this will be greatfully appreciated.
simulation assurance auto
Hey…i must say " simply professional "
Good efforts…I am also working as a web designer as i am from art background.
I am more interested in flash animations/ sites.
Kris-I
Very cool sample. I’d like adapt it for my work. I’d like for each line have a delete button, after confirmation delete the line. Could you help me ? Thanks
Hakan
It doesn’t works correctly if jquery ui 1.8 included to page. I didn’t try other versions of ui.
Hakan
By the way, the add button works, but the delete button doesn’t.
zchef2k
I’d like to add on to the earlier question about the form elements being duplicated being <select> elements. In my code I have a the following (abbreviated) HTML layout:
<div id="form1" class="clonedInput">
<label>blah</label><select>//auto populating from php//</select>
</div>
While I can get this script to work and add/delete auto populating select elements, the adding of the name attribute is applying to the labels, not the selects themselves. Therefore, I am not able to POST any unique variables aside from the original select element.
How can I get the ‘name + 1′ routine to apply to the select element, not the labels?
Finau
Great work and thanks for sharing your work with us,
thanks a lot
azrain
hi,
good tutorial. i really need it. however, just want to add, if you want to clear the value of cloned input element:
line 14: var newElem = $(‘#input’ + num).clone().attr(‘id’, ‘input’ + newNum).val(”);
that’s all.
azrain
sorry wrong line. this is the correct one:
line 16: newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum).val(”);
sorry
Raymond
Great walk-thru, nicely done. However (uh oh), there are two issues with it (one minor and one less minor). First, the minor issue – when you clone a field,
if it already has been filled in which would seem likely, then the clone carries with it the filled-in value. I think this could be easily rectified by simply blanking
out the value of the newly created element after its creation (hence the "minor" part). The more problematic issue I see, and I’ve seen this with more than one
other similar script and one jQuery plugin that attempts to package this behavior is the way element names are addressed. In a backend/server-side language
that would process the results of a POST or GET from your form, the simple and expected behavior (I think) would be for elements that are essentially multiples
or clones of one another to have different IDs for referencing purposes but the same name, and have the name include ‘[]‘ to indicate that the field is an array.
So, instead of winding up with $_POST['name1'], and $_POST['name2'], etc. (in PHP, for example), you would have $_POST['name'][0], $_POST['name'][1],
$_POST['name'][2], and so on, which greatly simplifies processing the output (all the $_POST['name'][??] elements can be handled together as one unit, looping
through them, instead of having to inspect each $_POST[] variable’s name and see if it includes a substring called ‘name’ which is what would be required
with the present scheme. Thoughts?
Raymond
Feeling guilty about being so lazy (above). So, I decided to give it a go
and realized both issues referenced above can be addressed with fairly
unobtrusive changes to just two lines of your rather cool code:
Change line 16 from:
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
To:
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).val(”);
Change line 43 from:
Name: <input type="text" name="name1" id="name1" />
To:
Name: <input type="text" name="name[]" id="name1" />
To test this I’ve set the form’s method to "post", added a "submit" button to the form,
and placed the following PHP excerpt at the very top of the page to simply display
the values posted from the form:
<?php
if (isset($_POST['submit'])) {
echo "<p>Results of form submission:</p>\n";
echo "<pre>";
print_r($_POST);
echo "</pre>\n";
echo "<hr /><p><a href=’" . basename(__FILE__) . "’>Reload Charlie’s Very Cool Form</a></p>\n";
die();
}
?>
Now, to make the newly added fields auto-focus upon creation… perhaps something to save for
the next go-round. Hope someone finds the above minor suggestions useful! Again, great work!
Zilus
Awesome!! Just what I was fighting with…
izoel
Great post, ok.. i would like to make it short question , all in here already mention about PHP etc , my question ..do we have to put unlimited variable for that clone to mysql table ? thanks for answer
Peter L
I am a rank newbie to jquery, so forgive me if this seems like a goofball inquiry.
Is there a way to auto number lines that are added when you click the add button?
For instance, the first line starts with "1". When the user clicks to add another form element, the second line starts with "2", etc.
I know your time is important and any illumination you can give me will be very much appreciated.
Peter
Tim
How would you go about numbering the label text, such as Name1:, Name2:, Name3: etc.?
Haze Long
thanks Charlie, you helped me alot with this article in a current project that I was working on. I actually implemented it in a sliding form that automatically adds height each time a row is added. Wouldn’t have been able to do it without your help
cheers.
Greg
What is the fix for firefox that isn’t posting the dynamically added inputs?
Beauford
I too am trying to add multiple inputs, but I am completely lost as I know nothing of jquery. I have 5 inputs on one line that I want to duplicate, each one has a different name so I understand I need to loop through so each one is recognized and a new number is added to each different input, but how to do this eludes me. Any help would be much appreciated. Below is where I have started.
Thanks
<form id="myForm">
<div id="input1" style="margin-bottom:4px;" class="clonedInput">
<table style="width: 776px" cellspacing="0" cellpadding="0">
<tr>
<td><input type="text" name="quantity" id="quantity" value="" style="width: 50px"></td>
<td><input type="text" name="part_number" value="" style="width: 75px"></td>
<td><input type="text" name="partsdesc" value="" style="width: 177px"></td>
<td><input type="text" name="supplier" value="" style="width: 140px"></td>
<td><input type="text" name="parts_invoice_id" value="" style="width: 90px"></td>
<td><input type="text" name="parts_eta" value="" style="width: 90px" readonly>
<script language="JavaScript">
new tcal ({ ‘formname’: ‘invoice’, ‘controlname’: ‘parts_eta’});
</script>
</td>
<td> <input type="text" name="unitprice" value="" style="width: 100px"></td>
</tr>
</table>
</div>
<table id="parts" style="width: 776px" cellspacing="0" cellpadding="0">
<tr><td height="10" colspan="7">
<input type="button" id="btnAdd" value="add another name" />
<input type="button" id="btnDel" value="remove name" />
</td></tr>
</table>
</form>
OpenBSD
Hi,
This Worked Perfectly. But i ihave any question:
how to send this form multiple data ? any submit button for send data (resualt) to database?!
Thanks
OpenBSD
Hi, this worked perfectly but i have multiple input in my page. how to set this plugin for one ?
example :
<input id="name>
<input id="name2"">
i need to add only for name input ?! how to ??
thanks.
Mike
If you’re having troubles with this not auto-incrementing the field, it may be because you’re using a <label> field. The script changes the name/id of the first child so if your <label> appears before the <input> in your HTML it won’t work. Obviously it doesn’t matter which order these appear in the HTML so just swap them round and let CSS position the label correctly.
Hopefully this will save someone the hour or so I just wasted!
Allie
Hello! Please pardon any ignorance in my question. I am relatively new to JQuery as I have developed some using it, but not terribly much. First of all, thank you for your brilliant post. It has helped me a lot. Second, to my question. Of course, if anyone knows the answer to this, please feel free to answer. I am wanting to use an onKeyUp event with the new form fields that are created. In the onKeyUp event, I would like to take the value of one field, do a function on it using the value of a 2nd field, and enter the result in a 3rd field. Any insights? I currently have this functionality working on the site I am developing, but it is not now dynamic, and we are wanting to make the fields dynamic and be able to add to them. I realize this may seem like we are putting the buggy before the horses, but it is the way the site has been developed thus far (sorry!) Anyway, any help that anyone could give me would be GREATLY appreciated. Thanks so much!!!!!!!!
Sandy Ressler
just had to tell ya the article is awesome…well written and damned informative…keep it up!
kelvin
Great post but it does not allow a user to dynamically add & remove textbox of different iteration on the same page, an example that i have can be seen here, https://docs.google.com/leaf?id=0B0tC33MqRSdsZDdiZDM2MDMtMzU3ZC00MTIwLTg2ZDctODIyN2ZmNmQwZWIy&hl=en
Andy
The remove button doesn’t work correctly in jQuery 1.6.
I’ve tested in 1.3, 1.4, 1.5 and it works in those.
George
hi frnds,
how to clone with table?
eg:
<div id="input1" class="clonedInput">
<table>
<tr>
<td>
text1
</td>
<td>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
text2
</td>
<td>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</td>
</tr>
</table>
</div>
tre
hi Charlie, want to say thanks for this great tutorial. it just works, easy to understand, simple and elegant. thanks once again
Allan
Really great, but my solution is part of this, i use an array of fields and duplicate some part of the form! But great , thanks.
kjetilengen
Does somebody have a finish solution with more than one field? I’m a bit lost when it comes to Javascript and would really appriciate if somebody please could help me out with this
DavidGoodman
I am not very good with JS or jQuery, but I spent the last hour or so trying to fit my (and others’) needs. I am happy to report that I did it!! This isn’t the most efficient solution, but it works.
To implement this for more than one field simply change
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
to
newElem.children(‘:eq(0)’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
Then you will copy and paste for each field you have, changing the eq to the placement of the field and the attribute names to the respective field. An example with 3 fields is below:
In this example replace:
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
With:
newElem.children(‘:eq(0)’).attr(‘id’, ‘firstname’ + newNum).attr(‘name’, ‘firstname’ + newNum);newElem.children(‘:eq(1)’).attr(‘id’, ‘lastname’ + newNum).attr(‘name’, ‘lastname’ + newNum);newElem.children(‘:eq(2)’).attr(‘id’, ‘email’ + newNum).attr(‘name’, ‘email’ + newNum);
And of course, the html would change to:
<div id="input1" style="margin-bottom:4px;" class="clonedInput">
First Name: <input type="text" name="firstname1" id="firstname1" />
Last Name: <input type="text" name="lastname1" id="lastname1" />
Email: <input type="text" name="email1" id="email1" />
</div>
ayman elsayed
Thank you SO much .
it meets my needs
kjetilengen
Halleluja!! Thank you!! Just what i needed!
kjetilengen
@DavidGoodman:
Thank you for posting the solution with multiple fields. What do i have to do if i want a div around each of the elements?
Tristan Denyer
I too was looking for a way to duplicate multiple labels, inputs and selects, but also maintain accessibility so that the for attribute in <label for="name"> matches the id="name" in the <input…>
In fact, I had 36 attributes I had to ensure were not only sequentially numbered, but also matching in their respective areas of the form so that <label for="name"> and id="name" became <label for="name2"> and id="name2".
Combining the comments and suggestions found above, and doing some trial and error, I think I have come up with a solution that does it all.
The change in the original code is swapping
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
for
newElem.find(‘#label_fn label’).attr(‘for’, ‘first_name’ + newNum);
newElem.find(‘#input_fn input’).attr(‘id’, ‘first_name’ + newNum).attr(‘name’, ‘first_name’ + newNum).val(”);
newElem.find(‘#label_ln label’).attr(‘for’, ‘last_name’ + newNum);
newElem.find(‘#input_ln input’).attr(‘id’, ‘last_name’ + newNum).attr(‘name’, ‘last_name’ + newNum).val(”);
newElem.find(‘#label_ttl label’).attr(‘for’, ‘title’ + newNum);
newElem.find(‘#select_ttl select’).attr(‘id’, ‘title’ + newNum).attr(‘name’, ‘title’ + newNum).val(”);
newElem.find(‘#label_cat label’).attr(‘for’, ‘category’ + newNum);
newElem.find(‘#select_cat select’).attr(‘id’, ‘category’ + newNum).attr(‘name’, ‘category’ + newNum).val(”);
newElem.find(‘#label_eao label’).attr(‘for’, ‘email_address_officer’ + newNum);
newElem.find(‘#input_eao input’).attr(‘id’, ‘email_address_officer’ + newNum).attr(‘name’, ‘email_address_officer’ + newNum).val(”);
(I’m don’t hold a blackbelt in jQuery, so I am pretty sure someone here can write this more efficiently.)
The full explanation, working form demo, and code is here:
http://www.tristandenyer.com/blog/jquery/using-jquery-to-duplicate-a-section-of-a-form-maintaining-accessibility/
Would love to get feedback on making this version more efficient, yet maintain the accessibility aspect.
Thanks Charlie for great code to begin with!
Dn
I really liked the form. I have a simple question. I want to add a heading to my inputs that I want to dynamically change with each added input. Is that possible?
I have just started using jquery and I dont seem to get this working
yuvaraj
Charlie,
excellent way of teaching the newbie who wants to learn jquery. you have done a great job.
XDude
Thank you sir! Beautiful!
DavidGoodman
Ok everybody.. A follow up to my previous post that addresses some issues I ran into. First, when placing multiple forms on one page, I was getting conflicts. This has now (mostly) been resolved. Also, I didn’t like the idea of having to add js for every element, so I added a loop to make this whole thing dynamic.
I have completely reworked the entire script so I will not try to tell you what to modify, and instead show you the entire new script.
<script type="text/javascript"> function trimNums(stringToTrim) { return stringToTrim.replace(/\d+$/,""); } function dupForm(divId, divClass, btnAdd, btnRm) { //alert(divId+' '+divClass); var num = $(divClass).length; var newNum = new Number(num + 1); var i; var newElem = $('#' + divId + num).clone().attr('id', divId + newNum); for (i=0; i < newElem.children().length; i++) { var attrId = trimNums(newElem.children(':eq('+i+')').attr('id')); var attrName = trimNums(newElem.children(':eq('+i+')').attr('name')); newElem.children(':eq('+i+')').attr('id', attrId + newNum).attr('name', attrName + newNum); } $('#' + divId + num).after(newElem); $('#' + btnRm).attr('disabled',''); if (newNum == 15) $('#' + btnAdd).attr('disabled','disabled'); } function rmForm(divId, divClass, btnAdd, btnRm) { var num = $(divClass).length; $('#' + divId + num).remove(); $('#' + btnAdd).attr('disabled',''); if (num-1 == 1) $('#' + btnRm).attr('disabled','disabled'); } </script><form id="myForm" action="temp.php" method="post"> <div id="input1" style="margin-bottom:4px;" class="clonedInput"> First Name: <input type="text" name="firstname1" id="firstname1" /> Last Name: <input type="text" name="lastname1" id="lastname1" /> Email: <input type="text" name="email1" id="email1" /> </div> <div> <input type="button" id="btnAdd" onclick="dupForm('input', '.clonedInput', 'btnAdd', 'btnDel');" value="add another name" /> <input type="button" id="btnDel" onclick="rmForm('input', '.clonedInput', 'btnAdd', 'btnDel');" value="remove name" /> <input type="submit" id="submit" value="Submit" /> </div> </form>Ok.. Now a little explanation..
Simply add the functions to your js. Then for each implementation make onclick="dupForm(‘input’, ‘.clonedInput’, ‘btnAdd’, ‘btnDel’);" (and rmForm respectively) where "input" is the id of the div (or other element) to be cloned, ".clonedInput" is the class of the div, and btnAdd and btnDel are the respective names of the buttons.
This works for an unlimited number of divs on each page to be duplicated, as well as duplicates an unlimited number of children for each div. So far, it does not work recursively, but it will get you started.
Thanks Charlie for getting me started!!
Bobbi Martin
I am having an issue with the new code you created. And, I am not sure how to fix them.
01. I have organized my form using tags. In the orginal code I could attach the ” [id="input1" style="margin-bottom:4px;" class="clonedInput"]” attributes to the and have it clone the . It would add a new but didn’t create unique IDs or Names for the new fields. Can I do this?
02. I tried your new code using my setup, but it wouldn’t clone the so I put the in a with the attributes. It wouldn’t clone. I stripped out the list tags and it still wouldn’t clone. The problem is the “field titles” can’t be in any tags (, , , etc) for the clone to work. Is there a fix for this?
03. If the field is required, then I have an “[*]“, but it breaks the clone feature. So, I can’t do much styling.
04. Is there a way to clear the cloned fields?
Bobbi Martin
Err.. The comment censored out my HTML tags. I formatted/styled the form using an ordered list and each field is in an “li”.
Ab Hakam
Thanks DavidGoodman, your code help me a lot and save me a lot of time from editing both the form and jquery code.
I also did a little modification (thanks to Raymond)
1. clear previous value when adding new form element
2. change the input value to POST array values
FIRST CODE
line 21 : newElem.children(‘:eq(‘+i+’)').attr(‘id’, attrId + newNum).attr(‘name’, attrName + newNum);
to
newElem.children(‘:eq(‘+i+’)').attr(‘id’, attrId + newNum).val(”);
and
SECOND CODE
change all the value in name in the input tag to arrays
name=”firstname1″
name=”lastname1″
name=”email1″
to
name=”firstname[]”
name=”lastname[]”
name=”email[]”
Just print out the $_POST value to see the result
echo “”;
print_r($_POST);
echo “”;
Diego
David Goodman,
Your way, for me, it´s better. But it doesn´t work if the html form have line breaks tag or paragraph tag inside it.
How can i solve this problem? For allow duplicate forms with elements in separate paragraphs?
Thanks
DavidGoodman
@kjetilengen
If you use my new code (posted just above) you can change the for i loop to this:
for (i=0; i < newElem.children().length; i++)
{
var attrId = trimNums(newElem.children(‘:eq(‘+i+’)').attr(‘id’));
var attrName = trimNums(newElem.children(‘:eq(‘+i+’)').attr(‘name’));
newElem.children(‘:eq(‘+i+’)').attr(‘id’, attrId + newNum).attr(‘name’, attrName + newNum);
for (j=0; j < newElem.children(‘:eq(‘+i+’)').children().length; j++)
{
var childAttrId = trimNums(newElem.children(‘:eq(‘+i+’)').children(‘:eq(‘+j+’)').attr(‘id’));
var childAttrName = trimNums(newElem.children(‘:eq(‘+i+’)').children(‘:eq(‘+j+’)').attr(‘name’));
newElem.children(‘:eq(‘+i+’)').children(‘:eq(‘+j+’)').attr(‘id’, childAttrId + newNum).attr(‘name’, childAttrName + newNum);
}
}
That will work for up to "generations" after your original div. It will allow you to enclose each child element in its own div (or group them into divs)
Henri
In the demo when you add some extra fields, fill them, remove them and add new fields again, the previous entered names are still there. Is it not possible to remove the content of the field together with the field itself?
But besides that little glitch, what is the use of a form without a submit button ???? When you add extra fields, the sourcecode still only displays the original fields, so how are the extra fields submitted to lets say a php file for further processing?
Ismael
Can you help me with this please ?
Now when i click "add" new inputs are there.
but how to get them in the next page using php
for example
<input type="text" name="name1">
when i add another, the text i’ve added on the second doesn’t show for me !
i hope i made it clear, sorry for my bad english
Ismael ..
Jamie
Thank you for this post. It was very well-written and very helpful. I can easily modify it to suit my needs. Kudos!
platypusman
I get a 404 error on the demo:
http://charlie.griefer.com/blog/pages/jquery_dynamicFormElements.cfm
Charlie
Yeah, sorry about that. I just recently migrated my blog from BlogCFC to WordPress, and need to update those pages and links. Hopefully soon. Perhaps this weekend.
Charlie Griefer
Just a quick FYI, I’ve migrated the demo page into the new blog, and updated the link.
To save folks from scrolling up, the demo can be found at http://charlie.griefer.com/blog/jquery-dynamically-adding-form-elements/
I did have to make some small modifications to the jQuery, as the buttons aren’t functioning properly in jQuery 1.6. I will get the blog entry itself updated shortly, but for now, please enjoy the demo.
Travis
I used this code and I wanted to mention that when you clone the input field, you will also need to clear the previous value of the cloned input. If you type all your information in and click add, that input will be cloned with that data which could confuse your end users.
just add: .attr(‘value’, ”); to the end of the newElem.children line
This should be amended to this tutorial. Also it would be most helpful with a tutorial on how to then validate dynamic inputs like this.
Peter
I used you script ot duplicate dropdown boxes, in combination with a script to dynamic load a second dropdown from a database depending on the selection of the first dropdown. (this to make recipies and add ingredients)
I now face a challenge where i have to use the cloned dropdownbox to trigger the database update. So far i can only use the original dropdown in jquery, the cloned one does not trigger jquery. Not even an simple alert. When i do a loop to alert all the id’s in the form the clode dropdowns are there
Can you put me on the right track how to trigger an alert message from the cloned dropdown?
Charlie
@Peter:
You’d need to use jQuery’s live() method. If you add an element to the DOM after the page has loaded, jQuery cannot hook into that element to trigger events… *unless* you use live() when creating the element.
So let’s say you used the following code to create the element:
$('#btnAdd').click(function() { // do some stuff here });Change that to:
$('#btnAdd').live('click', function() { // do some stuff here });See http://api.jquery.com/live/ for details. If you have questions, let me know and I can whip up a quick post.
Peter
@Charlie,
Thanks for the reply, i upgraded to JQ1.6.2 and for some reason (new to JQ) the .live is not needed (did implement it though). I had to change the enable en disable of buttons to the .prop function as the .attr is not working correctly anymore.
Now i have the problem that the second dropdownbox is not filled when it is a cloned one. The code to clone is:
var newElem = $(‘#input’ + num).clone(true, true).attr(‘id’, ‘input’ + newNum);
// manipulate the name/id values of the input inside the new element
newElem.children(‘:first’).attr(‘id’, ‘ingredient_cat’ + newNum).val(”);
newElem.children(‘:last’).attr(‘id’, ‘ingredient’ + newNum).val(”);
I used the same name of the fields with a [] for php processing.
Any ideeas on that? Before the none responsive cloned select’s and the upgrade from 1.4.4 to 1.6.2 this worked perfectly.
Peter
Update:
It seems to be a IE8 (only version tested) issue, When i use FF3.6 it works like a charm.
Charlie
@Peter – Unfortunately, being a Mac guy, it’s a pain for me to test things in IE. I simply don’t have time at the moment to fire up various VMs in order to try and troubleshoot whatever’s going on in IE8
If you do happen to figure it out, please reply back though, as it may help others.
johan
thanx you very much!!!!!
kv
Hi Charlie,
After adding tables in div, how do i assign the name/id?
Without tables, i can just use eq(x) , replacing :first
// manipulate the name/id values of the input inside the new element
newElem.children(‘:eq(0)’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
Reason
YesNo
Yes
No
subdesign
“Name: ” should be removed from code because it will be the in the newElem.children line… thats why all values are repeated in fields.
Of couse modifying code is better currently have no time only for a quickfix.
subdesign
So one more time “Name br” html tags should be removed…..
RS
Hello Charlie,
It is a very nice code it works perfectly. But I tried to implement in a table row it seems doesn’t work. It just not add a new row that has few text boxes. Can anyone guide me how to use the code for a table.
Thanks guys!
André
This was exactly what I was looking for!
Great tutorial. I am now one very happy camper
stan555ley
Thanks a lot man this what is was looking man good work…..best wishes
Marz
The “Remove” button does not work with jQuery 1.6
Tristan Denyer
Christiaan helped me get mine working with the latest jQuery library 1.7.x:
“For later version of jQuery, change the button code to either
$(‘#btnDelW1′).attr(‘disabled’,true);
or
$(‘#btnDelW1′).attr(‘disabled’,false);
———-
I updated my forked version of Charlie’s plugin with Christiaan’s input and it worked. See demo and download for updated code: http://digitalmeaning.co/thoughts/using-jquery-to-duplicate-a-section-of-a-form-maintaining-accessibility/
Mark
The cloned input fields do not register as $_POST data with form submission when :first is used (line 18). Use instead the id (or class) of the parent. In the example above, the parent has an id ‘name1′ so the change would be from:
newElem.children(‘:first’)…
to
newElem.children(‘#name1′)….
John Azuka
Please i have a form that has textfields dynamically generated and work fine.but i want to have one of the field display from the database for each of the lines.how do i do that?
Nature_girl151
I love this tutorial, but I am having validation issues. Every time I try to add validation (i have modified the form to have 4 fields and a file upload) the form breaks and I cannot duplicate the fields. I also cannot get the fields to duplicate empty. I tried adding .val(”); to the the end of the line
newElem.children(‘#name1′).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum).val(”); ut that did not help.
Do I need a line(like above) for each of my form fields?
Here is my validation code- It is probably a placement issue – but I am a newbie at this and still working on it.
$(“#FileUploadForm”).validate({
groups: {
DocInfo: “Doc_Name Doc_Desc Pub_DateC”
},
errorPlacement: function(error, element) {
if (element.attr(“name”) == “Doc_Name”
|| element.attr(“name”) == “Doc_Name” )
error.insertAfter(“#Doc_Name”);
else
error.insertAfter(element);
},
rules: {
Doc_Name1: {
required: true,
minlength: 2
}
,Doc_Desc1: {
required: true,
minlength: 2
}
,Pub_DateC1: {
required: true
}
}
});
console.log(‘r’);
Any help is appreciated.
Thanks
Michael
On the demo:
http://charlie.griefer.com/blog/jquery-dynamically-adding-form-elements/
The form input id is not updating. The div and br id’s are, but the input id is not.
For example, on the third clone, here is what is displaying:
Name:
Is this a bug? I need unique id’s form my form elements! Please help!
Foxhoundn
Hey Michael,
instead of :
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum).attr(‘name’, ‘name’ + newNum);
do this :
newElem.children(‘:first’).attr(‘id’, ‘name’ + newNum);
newElem.children(‘:first’).attr(‘name’, ‘name’ + newNum);
The name and id will change as they should.
Michael
Can you take a look at my StackOverflow post?
http://stackoverflow.com/questions/8032202/dynamically-adding-form-multiple-elements-within-div
The example I posted there has two form elements there, but I’d like it to work for even more.
Any ideas?
Pradip Chitrakar
take a look at this page
http://ewizard.co.cc/how-to-dynamically-add-remove-validate-form-fields-in-jquery
it shows how to dynamically add, remove and validate form fields in jquery.
John
Your posted URL is broken.
I found the article here:
http://ewizard.co.cc/blog/how-to-dynamically-add-remove-validate-form-fields-in-jquery
Adetunji
I could not but make a comment after coming across this blog, u have done wonderfully well. I hve been on this for days. Thanks a lot.
Vikrant
Hi Charlie
Thanks a lot for this great post and work.
Web Design Crawley
Hi this is a great script but in the example the name and id’s of the inputs are not being incremented.
also If I have a h2 tag in the form how can I increment the value of it? e.g. name 1
^duplicated form will be
name 2
thanks.
Raygo
Hi! Great code! I’m using it right now for my last project! I just have a problem, the delete button is not working. I had the fields in tags and now in a table, but still doesnt work, any suggestions?
John
If you want to use jQuery 1.6 or newer you simply need to change all instances of “.attr” into “.prop”
Tyler
@John
This change from .attr to .prop fixed my issue with the btnDel not working properly. However, I found that the “name” attribute of an input field didn’t update properly with .prop on form labels (the only item I tested) so I changed it back to .attr
This is using jquery 1.7.1
Tristan Denyer
(Yeah, I posted this above, but wanted to make sure you saw it too) Christiaan helped me get mine working with the latest jQuery library 1.7.x:
“For later version of jQuery, change the button code to either
$(‘#btnDelW1′).attr(‘disabled’,true);
or
$(‘#btnDelW1′).attr(‘disabled’,false);
———-
I updated my forked version of Charlie’s plugin with Christiaan’s input and it worked. See demo and download for updated code: http://digitalmeaning.co/thoughts/using-jquery-to-duplicate-a-section-of-a-form-maintaining-accessibility/
AJ Mallory
Here is a more detailed explination of what is going on with .attr() vs .prop()
http://stackoverflow.com/questions/5874652/prop-vs-attr
It seams like it makes more sense to use .prop() but there still my be issues, see the above link.
Raygo
that fixed my problem! thanks!
Raygo
I’m trying to use this plugin with the autocomplete plugin. Whenever I clone the input the autocomplete doesnt work in the cloned input. Any idea of why it happens?! Thanks
Mario
@Raygo Did you solve your problem? I have the same problem with autocomplete.
Tbone
I am using the code with multiple input fields. All works fine until I add a tag. I believe the code is trying to duplicate it or something? How do I have the code ignore the elements? I am trying to style the form a bit and adding line breaks, breaks the form.
Thanks
tbone
adolfoshitler
nice work there!! its neat and functional=) but i have few questions…
>it seems it just DELETE the last inserted element but how to delete those are at the top??
>i cant figure out how to send the VALUES from the added elements to php with the use of ajax or $.post or even .load() in jquery please cite more example=)…
thanks alot!
snipe
Hi Charlie – thanks for the great post. I made some tweaks to make it work in jQuery Mobile, and change the text label on the add button once the limit has been reached. You can check it out here if you’re interested.
http://www.snipe.net/2012/02/jquery-mobile-add-remove-fields-dynamically/
Help
Hi
I am fairly new to jquery and php. I have created a simple form in HTML and did simple PHP coding to print the results from what was entered in forms. I have looked at this tut (its brilliant). I have tried to do what you have in this blog and its working but somehow i cant get it printing in my results from php file.
Thanks
skotperez
Hi Charlie, great and simple code.
Just one thing. In my case, the following lines doesn’t work:
$(‘#btnDel’).attr(‘disabled’,”);
$(‘#btnAdd’).attr(‘disabled’,”);
And I have to set to false your empty field to make it works:
$(‘#btnDel’).attr(‘disabled’,false);
$(‘#btnAdd’).attr(‘disabled’,false);
Thanks for the code, anyway.
Diogo
Please, let me know how do you save the data into a prostgreSQL database (for example).
I´m using your code with an extra line after
newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum); //new line newElem.children(':first').attr('id', 'name_check' + newNum).attr('name_check', 'name_check' + newNum);I also introduced the line:
Now I want to only send to the DB the values there are associated with a checkbox checked…but I’m having troubles with that.
David
I did not see this above but maybe I over looked it. How would you make a second div clone the fields independently of the first div? What I have is a section for new user that they need to add and also a second section where they need to add multiple listing. The first div works but I can not get a second div to work.
David
How can I get this code to loop correctly? What I have is say 3 fields User, Password, Email when the PHP array displays it goes
User 1
User 2
Password 1
Password 2
Email 1
Email 2
I need to to go
User 1
Password 1
Email 1
User 2
Password 2
Email 2
Pinchas
A fantastic job…thanks so much! Clean and Clear.
I chose to look for the object directly as opposed to positioning.
newElem.find(“[id^=Note]“).attr(‘id’, ‘Note’ + newNum).attr(‘name’, ‘Note’ + newNum);
Thanks, Pinchas
kakam
very good work but i have a little problem. After an additional input has been added and you refresh the page, the input box goes back to only one. I want to know if there is a way to make the additional input box stay on page even on page load ie if sessions can be created for that matter
Sanjana
hey,it is an awesome code and helped me a lot.
can you please tell me what are the ids of the fields product, kg and packets..so that i can enter them in database…
thanks in advance..
Dr3am3rz
Hi Charlie,
I have integrated your code but I need to ask how am I supposed to add a new field without cloning the originally text inside the field that’s displayed?
Regards,
Jeffrey
Rahul Sati
Hi Charlie,
First of all thanks for the code man, it really helped me a lot. I don’t know if you visit this link anymore but i have a query, i am making a game application for kids using html5, jquery and javascript and the admin can add as many user as he wants, but my problem is i am not using any database so all will be local storage and it will be native app, so can you please tell me how can i achieve this, also only those users that have been added by admin will be shown, so the storage problem is there but i know it can be maintained but don’t know how. so will you please help me out, its kind of urgent.
Regards
Rahul
cacimaki
Thank you, this is very helpful.
I would like to see this jQuery combined in PHP
Oxydium974
Thank’s a lot for your perfect tutorial. Everything works fine for me except the Delete button. I work with JQuery 1.7.2.
To fixe the problem, I change :
$('#MyElement').attr('disabled','');by
$('#MyElement').removeAttr('disabled');If disabled attribut is in a button, HTML5 will disabled the button so you have to delete the attribute.
.
Maybe you should try it @Moty
Moty
this code doesn’t seem to work in jQuerty 1.6 and later, anyone knows why ?
Cory
For one, you would have to use prop instead of attr.
Oxydium974
I didn’t reply to the good person :p. You should look at my answer on the top (to cacimaki) if you want to fix your problem.
Jeff
what can I say without repeating everyone else.
I was looking for a quip that would let me ad a series of fields as the user clicks add so rather than add just a name it would add name, relation, etc per click.. and as long as I kept the fields in the container div with the id=”clonedInput” it would add all fields…
REAL COOL
BUT… for some reason it will not allow me to delete the button is greyed out.
I attach a link to a test page http://www.measureofhope.org/test.html any idea as to why it won’t remove the fields?
Jeff
okay so i was able to get the fields to add and to delete but for some reason the the delete button will not grey out when there is only one field.
Also is there a way I can have multiple instances of this on a form… Please see
http://measureofhope.designedbyjeff.com/testChiPPupdate.html
I had it working with one but the moment I entered another it disabled them all.
Your advise is appreciated.
Brian
Hello,
I’m having a problem in implementing this code. I’m using google app engine with jinja2 to render my html templates. The page in question loads without any errors, but when I click the button used to add an input box to the page, the box flickers on screen and the form submits, with a blank screen being rendered afterwards. I’m assuming this has something to do with my GET or POST requests being improperly formatted, but I just can’t figure out exactly what is happening. Does anyone on this site have any insight?
Ed
Thanks for the code – really well explained for me as a jQuery newbie and exactly what I was looking for.
Pascal
Thanks a lot for your effort! Really great tutorial and saved me a lot of time!
Cheers
Shilpa Sonawane
Thanks for the code and the explanation you have provided.its really very nice and easy to understand for beginners.I have one problem I want to add date-picker to dynamically created form text field.how to do it?I have searched over net but didn’t got solution.help me
kiel
Im interested in the css trick display to none, Could you please teach me how to do it?? Please
Charlie
Not sure which “trick”… jQuery’s built-in .show() and .hide() functions are the equivalent of setting an element’s CSS display property to either “block” or “none”.
kiel
“What you really want to do is show a minimal amount initially, and then give the user the option of adding as many more (within reason) as that particular user might need. You might go about doing that by creating 100 fields and setting their CSS display attribute to “none” “.
This is what im talking about. I want to dynamically add fields but not using javascript. Can i do it in Php only?
Charlie
You can do it in PHP if you’re OK with the page being refreshed. You’d click the “Add Another” button which would submit to the server, presumably with a hidden form field whose value is the number of fields currently shown (assume 1 by default).
The server would then increment that value and re-load the page. You’d then use PHP in the view to render ‘x’ number of form fields, where ‘x’ is the incremented value.
I’m not a PHP developer, so can’t give you any code to go on there… but it’s a fairly straightforward process. No different than any other communication between the client and the server facilitated by PHP (or any server side technology).
gauz
it helping me alot, thank you Charlie and Goodman.
Dr3am3rz
Hi,
I have a few inputs in 1 ul li list.
Example:
I would like to duplicate this block every time the user clicks add button. I wonder is it possible to use your code to edit to get what I wanted? And at the same time there’s no limit to the number of times to add.
Thanks.
http://tinyurl.com/dacmreed22437
“jQuery – Dynamically Adding Form Elements @ Charlie Griefer” ended
up being seriously engaging and beneficial!
In todays universe that’s tricky to deliver. Thanks a lot, Finlay
Hash
It doesn’t work with me
Swathi
Great article. Thank you So much. It helps a lot. Greatly Appreciated.
Immigration Solicitors Hackney
I don’t even know the way I finished up here, but I believed this publish used to be great. I do not recognise who you are but definitely you’re going to a well-known blogger in the event you aren’t already. Cheers!
Raju
tutorial is good
Raju
It is good,how to display check box and their label dynamically on entering a value from jquery popup box
Raju
How to display check box and their label dynamically on entering a value from jquery popup box