Using jQuery to duplicate a section of a form, maintaining accessibility

July 2013: I have moved this plugin to GitHub. All future versions and work will be hosted there. Please visit the project page for downloading, forking and contributing. You may continue to leave comments below.

Demos

The old demo for this plugin can be found here: https://tristandenyer.com/demos/dynamic-form.html

Duplicate a whole section of a form
The new Bootstrap 3.4 demo for duplicating a whole section of a form can be found here: https://tristandenyer.com/demos/dynamic-form-bootstrap-3-0.html

Duplicate multiple elements independently (latest)
The new Bootstrap 3.4 demo supporting duplicating multiple elements independently can be found here: https://tristandenyer.com/demos/dynamic-form-bootstrap-3-3-4-multiple.html

A little history

I had a client who wanted to allow the user to dynamically add a section to their form. No problem, I thought. Then I noticed that the duplicated section was using the same name, id, and for attributes, which means that the resulting submission would not plug in nicely to the database.

First, I must give a huge thank you to charlie.griefer.com for his original code in the post “jQuery – Dynamically Adding Form Elements” It was exactly what I needed to start with. I then modified and added elements to get it to work in my form. Special thanks to those that posted in the comments section of Charlie’s page: David Goodman and “azrain” for help and inspiration.

Here’s the situation

  • Charlie’s used jQuery 1.3.; whereas I needed to make sure this worked with 1.5.1. (ver 0.9.3 now uses 1.9.1)
  • Charlie’s dynamic form only wrapped a single input. I needed to wrap an entire table inside a long form. (As of v.9, I am no longer using tables.)
  • The original code duplicated the user’s inputs from the original form. I needed a fresh, empty form.
  • The original code had a variable that sequentially numbered the 2 IDs and 1 name attribute on the new forms. But, it only had one input, no labels, and was using the :first selector to do so. This was not going to work in my situation where I needed to maintain the accessibility of matching the labels to the input attributes, and have it all sequentially numbered as the user added sections to the form.

In short, I needed to allow the user to add an empty form with unique IDs, names, and labels to maintain accessibility and work with the database.

Using input from the user comments on charlie.griefer.com, new jQuery selectors, and adding IDs to target the attributes I needed to sequence, I have rebuilt Charlie’s original code to suit my needs. Check out the demo here.

Future release plans

Below are my plans for the upcoming releases. If you have input on any of these functionalities, I would be happy to add your code and test it.

  • Assign focus to the first textarea of the added section, moving it up into the viewable area of the viewport. Tried it, and this just makes the experience a little odd in that it happens so fast the form looks like it is clearing instead of adding a section. Ver 0.9.3 now has focus on the first select in the duplicated field, but no slide into view.
  • auto tab
Dan Woodward reworked this plugin and created this great jsFiddle (http://jsfiddle.net/SFMTB/) showcasing numerous form elements all working and duplicating nicely. I decided not to add all of them to my demo and the download, but allow you to start with a basic form and add what you need.

One of my main problems was targeting the for, name, and IDs so that I could have them become sequentially numbered with each additional form. I ended up having to create unique IDs on the td, but am hoping one of you know of a better and more efficient way to do this. Simply targeting input or select in the jQuery selector didn’t work for me. And yes, I used a table because the original client this was built for requested it. A future version will do this using a table-less form.

Visit my GitHub repo for ver 0.9.5.0

Archives:

Previous version 0.9.3 download here »
Previous version 0.9.2 download here »
Previous version 0.9.1 download here »
Previous version 0.9 download here »
Previous version 0.8 download here »
Previous version 0.7 download here »
Previous version 0.6 download here »
Previous version 0.5 download here »

Since I am not yet a tenth degree blackbelt in jQuery, I would appreciate any and all input regarding the script and code, especially in how we can write it more efficiently.

Your input is always welcome: contact me or, better yet, leave a comment below.

120 Comments

Andy Moyle

Very helpful update on jquery form element cloning. I’ve got my form cloning properly – finally!

But (there’s always one of those in a comment;-)
I’ve got a show/hide thing happening on a select tag
that is triggered by
[sourcecode language=”plain”]<select name="ticket[]" id="ticket1" onChange="showhide(this.value,’hide1′)">[/sourcecode]
I can’t get hide1 to change in the onchange bit. I’ve tried
[sourcecode language=”plain”]newElem.find(‘select’).attr(‘onchange’, ‘hide’ + newNum).val(”);[/sourcecode]

but that isn’t doing it!

Any ideas what it should be?

Reply
tristan

I think I know what you mean. I too had a tough time with ‘select’, and I don’t why. That is why I had to use an ID on the td like this line:
td id=”select_cat”

Then in the js I had to write the following to get it to work – note the #select_cat ID before the select in the selector:
[sourcecode language=”plain”]newElem.find(‘#select_cat select’).attr(‘id’, ‘category’ + newNum).attr(‘name’, ‘category’ + newNum).val(”);[/sourcecode]

Using that logic, maybe we could do the same for yours? Can you place an ID on a block level element around your select and add that ID to the newElem like I did? Again, I don’t know why, but when the select was by itself as a selector, it just wouldn’t work for me, especially when it was in a table/td.

Also note that I have an ID of “category” for my select, and when I tried ‘select#category’ in the jQuery selector, it too would not work.

Also, try removing the “1” from ‘hide1’ in the onChange. After it duplicates, it should add it sequentially for you. maybe that’s hanging it up. Shouldn’t but, you know these things go.

Let me know how it goes for you.

Reply
Tyson

Great post. Can you point out what removes the value once duplicated. “The original code duplicated the user’s inputs from the original form. I needed a fresh, empty form.”

Thank you.

Reply
Tristan

Adding .val(”) to the line of jQuery with the “input” selector will ensure that the duplicated input shows up with an empty value. No need to add it to the lines that duplicate the label.

Reply
Jason

Thanks for the fantastic post Tristan. I’ve been trying to adapt Charlie’s code for multiple inputs and luckily found a link to your post in the comments! Very much appreciate your effort on this!

Reply
Dhimas

Thank you Tristan for the great tutorial.
I have a question, how do you limit the number of fieldset you can add?
let’s say if you want to limit the fieldset to 3. how do we do that?

Reply
Tristan

Download the plugin. Open the HTML file and look for line 37 or the following:
if (newNum == 5)

Change “5” to whatever maximum number of additions you want. In this case, 3.

Reply
marcelo

really great, but as it is a form, i need to get the cloned values from the $_POST (using php), how i do this?

Reply
Tristan

I’m unsure what you need to duplicate, exactly. But, I think you can duplicate just about anything, so long as you have to in the following string:
[sourcecode language=”plain”]newElem.find(‘#label_fn label’).attr(‘for’, ‘first_name’ + newNum);[/sourcecode]

Have you tried to wrap it in a span with an ID and place that in the #label_fn label ID above? The span would then be duplicated. You may not need the .attr(‘for’, ‘first_name’ + newNum) part, since this is to add a sequential number to the attribute ‘for’ of the form.

Maybe something like this?:
[sourcecode language=”plain”]<span id="example">$firstname = $_POST[‘data’][‘User’][‘firstname’];</span>[/sourcecode]

But, I am guessing here. Maybe someone else out there has tried this?

Reply
Mario

Hi!

Thank you. It is what I need for my project. But I have a problem with jquery autocomplete. Duplicated inputs don’t work with autcomplete, only the “original” input does. Any idea?

Reply
Tristan

Do you have a sample/demo we could look at? The plugin was designed to add a successive numeral to name and ID so that they are unique and don’t all go to the server with the same name and ID. If the plugin is adding a successive number to the attributes of the autocomplete, then maybe the script isn’t seeing it anymore? (I.E. class=”auto” gets turned into class=”auto2″ on the duplicated form.) Your autocomplete script may be looking for class=”auto” and ignoring class=”auto2″. If this is the case, you might need to add .auto2, .auto3, .auto4…to your script so that it recognizes them too.

Reply
Mario

Sorry, I don’t have a demo. That’s what I thought at the beginning: “The autoincrement must have change the autocomplete attribute”, but I’ve already checked the attribute class and it doesn’t change. That’s not the problem…

Reply
Tristan

Are you using a plugin for the autocomplete? If so, can you point me to the plugin to download? If not, is there a way you can zip up the code into an HTML file and send it to me so I can try it out?

My next guess is that the autocomplete doesn’t like there being two fields with the same attribute?

If you can create a test file, zip it up and send it to tristan // at // tristandenyer // dot // com , and I’ll try and take a stab at it.

Tristan

I downloaded and tested the plugin you mentioned and I got the same results as you. I also tried the ‘updated’ version and it didn’t work either. I tried it a bunch of different ways by trying to add the IDs into the form and hide them visually, or and couldn’t get it to work. I even added the successive IDs for the duplicated inputs (i.e. first_name2) into the JS on page load and it still wouldn’t work once the form was duplicated. In this mocked up demo http://digitalmeaning.co/demos/ac-form-test/demo/dynamic-form.html I added an extra input at the bottom for the first_name2 input, and it works on load, and after the form is duplicated. But the one used in the duplicated part of the form still won’t work.

I also tried placing the localdata in the page instead of it being linked to, and that didn’t help it either.

I think the form being duplicated somehow takes it out of the reach of the autocomplete JS. It’s like it doesn’t see it because it wasn’t there on page load. I don’t know how, or if it is possible, but it seems like you almost need to reload the JS each time a person adds to the form. This might allow the JS to see and connect to the added IDs? I don’t know; that’s a bit out of my ability/knowledge right now.

I looked around and saw some conversations about reloading JS after an event: http://stackoverflow.com/questions/8594408/jquery-reload-javascript-file-after-an-ajax-request I have no experience in this and couldn’t a quick demo to work. Maybe someone else might have an answer on this? I’m thinking that if you can reload the JS when the user clicks on the ‘add’ button, it might start working since the ID is now on the page when the JS reloads. Might have to place the JS at the bottom of the page too.

Sorry I could fix it, but will keep looking around for a solution.

Mario

I suspect AJAX could solve this problem. What do you think? If I make it work (unlikely), I ‘ll let you know. Thank you for your help.

Tristan

Cool! Glad it worked out for you. Thanks for letting me know.

If you happen to make any mods or fixes that others can benefit from, feel free to drop them here.

Reply
Cognis

I don’t think I’ll do any major modifications. It would be cool if I could clone just the table row instead of the entire table since I could just use and drop the labels but that’s not high on my list of priorities, but if I do it I’ll let you know.

Reply
Brian

Thank you for the detailed tutorial and everyone who comments! I managed to figure out how to implement this fairly painlessly on a current project of mine.

I’m currently in the same predicament as marcelo. My end goal is to be able to grab all of the data from the $_POST variable when the form is submitted. What I am wondering is if anyone has any ideas how to assign the form fields to variables so that they can be used in calculations. I am very new to jQuery and have decent JavaScript skills, but I am puzzled on how to use the field values when sometimes they exist and sometimes they do not. I have read other posts that describe storing the field names in an array which would allow you to loop through it. Is there a way to do the same thing in this scenario? Any comments would be appreciated.

Reply
Ken

Tristan – just wanted to thank you very much for posting this. It was exactly what I needed.

–Ken

Reply
Tristan

Thanks! Feel free to come back and post a link to your final, live product (if you can.) We would all love to see what you did with it.

Reply
Karina

I’m new on this… the code worked well!!! but I have a big problem I need to insert in a Database the fields…but in my database just inserts the last table …. how can I do to insert more than one table? any ideas? …. I need this urgently…

Reply
Tristan

Unfortunately I didn’t hook this up to the database. I only built the front end for the back-end developer to link up with the database. I know she used asp.net, if that makes a difference, but other than that, I wasn’t privy to how she go it working. Maybe someone on Charlie Griefer’s original comment thread has an idea? Or maybe someone here will be able to help out? Sorry I couldn’t be of more help with the actual database connectivity, but I am more proficient in front-end development. If you are using asp.net, I can reach out to my dev and see if she can help you. Let me know.

Reply
Tristan

Just posted it to FB and Twitter…hopefully someone will come by and have an answer for you.

Reply
Jeroen

Hi Tristan,
First of all: thank you very much for this post! It helped me so much!

I got my form working fine. Exept one thing.
In my form i have a radio buttons.
When I duplicate the form the radio button that was last selected by the user
is still selected in the new section. But I want nog radio buttons selected.

Is there a way to do this?

thanks!
Jeroen

Reply
tristan

Adding .val(”) to the line of jQuery with the “input” selector will ensure that the duplicated input shows up with an empty value. No need to add it to the lines that duplicate the label. See lines 11, 13, 15 above for an example.

I have been meaning to recreate the plugin using more form elements. Maybe I’ll do that soon and add some radio buttons.

Let me know if the .val(”) doesn’t work for you.

Reply
Dan

Use .val([]) instead. It will set an empty array of radio (and should work for checkboxes, too) values

Reply
Dan

Saw your update and needed to clarify – the .val([]) should be applied to radio or checkboxes only – adding .val(”) is the correct way to do it for text inputs

Reply
Tristan Denyer

I thought so, but didn’t see anything in the error console after I globally changed them. Thanks for clarifying that for me. I updated the demo and plugin to now use .val(”) and .val([]) appropriately.

Christi

You are my hero!!! You and those who have commented here have been TREMENDOUSLY helpful! This does exactly what I need it to, and now I also have an answer to the php question… took a look at the link you posted and it looks like what I will be needing! Keep your fingers crossed because when it comes to php there’s no such thing as a successful first run for me! Lol…

Reply
tristan

Thank you for the kind words! Glad it worked out for you.When you get it all working and live, feel free to come back and drop the URL here so we call all admire your work. Also, feel free to tell us if the PHP you are working on was a solution. You can post the code here to, or link to it somewhere.

Reply
Jay

Fantastic, this is great, using the logic behind the for a simple form I need to do … small ‘quirk’ I just noticed, if you add 5 sections then remove 1 (or all of them) you are no longer able to add any sections, its not a biggie, I just thought I’d let you know.

Reply
tristan

Thanks for the feedback! I fixed it and uploaded it as 0.9.1. Went ahead and made a couple small updates/tweaks to it as well. See changelog. If you haven’t made any changes to the plugin, you can overwrite the old file with the new one. If you did make changes, change line 40 [javascript]$(‘#btnDel’).attr(‘disabled’, true);});[/javascript] to the following: [javascript]$(‘#btnDel’).attr(‘disabled’, true);
// enable the "add" button
$(‘#btnAdd’).attr(‘disabled’, false);});[/javascript]
The patch above does not include the new .prop method to switch out the button values. It just fixes the bug. .prop method is in the 0.9.1 download js file.

Reply
Mike

Hey, you are a life saver thank you so so much for the help. Ben working with charlies code for ages and scrolling through the comments you came up top trumps!

One question, im using this in a form cloning about 5 text entry boxes. Do you know how I then add each of the inputs to the database? Do they each have their own id generated? (If you happen to know how to use redbean for it that would be the best but php I can figure it out from 🙂

Thanks in advanced!

Reply
Tristan Denyer

Do you mean aside from the action? [sourcecode language=”plain”]<form action="#" method="post" id="sign-up_area">[/sourcecode] I left this as a # placeholder because everyone will have their own URL/file that will be handling the server-side processing for the form. Some use .asp, some PHP… it’s up to you to decide what server-side form processing you need, and then plug it into this form.

You can also use this Javascript library for collecting form data: form2js https://github.com/maxatwork/form2js

Or, Convert HTML form into JavaScript object: jquery-serialize-object https://github.com/macek/jquery-serialize-object

Reply
Dan

Hi Tristan,

Dan here again. I could easily be missing something here but is there a reason why every form label & input is wrapped in an otherwise useless div? I went back over Charlie Griefer’s original blog post to see if he mentioned why and I can’t seem to find a reason.

I only ask because in applying this to my form I’ve discovered that

newElem.find(‘.inputsClass’).attr(‘id’, ‘first_name’ + newNum).attr(‘name’, ‘first_name’ + newNum).val(”);

does the same thing as

newElem.find(‘#input_fn input’).attr(‘id’, ‘first_name’ + newNum).attr(‘name’, ‘first_name’ + newNum).val(”);

only it lets me get rid of the #input_fn div and clean up my HTML a bit by referencing the class of the actual input, instead. Granted, doing it this way does force me to break convention and apply a unique class to every input & label, but I think the cleaner HTML outweighs the extra CSS classes.

In examining the live code in FF, Chrome & Opera it still slaps on a new number to the end of the cloned input’s name and id when I do it this way, but I’m wondering if I’m breaking something elsewhere by doing it like this. (Say in IE – not that anything weird would happen in IE!)

I haven’t gotten so far yet as to test form submissions to see if anything wonky is happening, but this question was gnawing at me.

Thanks for your thoughts!

Dan

Reply
Tristan Denyer

I haven’t refactored the code yet, as per your suggestion, but I think I remember doing it this way for a couple reasons. One was because back in the original versions of this plugin I was using a table for the form. I put the ID on the td. Why? Because I remember having trouble getting a class or ID on the input to work correctly.

Sounds like your newElem.find(‘.inputsClass’).attr(‘id’, ‘first_name’ + newNum).attr(‘name’, ‘first_name’ + newNum).val(”); works, and I looking forward to trying it out. I love getting rid of code, especially in forms. I’ll try this out for the next iteration.

Didn’t notice this earlier, but there is a problem with the form duplicating IDs… we should not have more than one unique ID on a page. After duplicating the form sections you end up with multiple IDs of the same name. Not good. So, refactoring to use your suggestion would make it more correct, and much cleaner.

Thanks for catching that! Hopefully get to it this weekend.

Reply
Tristan Denyer

Oh, one thing I just remembered: the select menus. I just reread one of my first comments and noticed that I had trouble with the select menus working until I placed the ID on the td (see Mar 25, 2011 comment above.) Have you tried your method on the select menus? I’ll be trying this first when I go to refactor it. Worst case we may have to use one div?

Reply
Dan

Its funny you should mention select menus – that’s what I was working with when I discovered class names work, too. I’m using a hide/show toggle script to display an OTHER text field when the select option “other” is chosen. The OTHER text input got a unique # added to the ID, but the select option’s value then had to match the new ID in order become visible – I tried applying a class to the select’s “other” option and it worked, the “select2” element included an option value of “other2” which the input id “other2” could reference. (Hope that all made sense – its 2:30 AM right now and I’m a bit tired and not sure it all came out right)

Since your reply I’ve tried every form element and input type I could think of and referenced only the CSS classes and they all work. I made a jsFiddle, too. See what you think: http://jsfiddle.net/SFMTB/

Reply
Tristan Denyer

All your input worked great (as you already know), and have helped make ver 0.9.3.

I did try to add a range slider to the form, but found that there was no feedback loop (no tooltip or number indicator telling the user what the range was. So, I added one. Then I found that it too got duplicated with the form and since it used jQuery to work, it was not allowing the indicator to duplicate and only be paired with its parent range element. A future plan will be to tackle a good UI for the range element and allow it to duplicate.

Thanks for all your input! I added your name to the credits on the 0.9.3 plugin. If you want anything more than just “Dan”, email me and I’ll update it. Let me know what you think.

Reply
kamran

Great post.

sir i want to add multple section in one page. for example in section one i want to add patient problems
and second section i want to add medication’s. i want to both section in one page. with single button. after that data insert into database.

Thank you.

Reply
Dan

Regarding the auto tabbing function that you mentioned you want to add – simply remove “tabindex = ‘x'” from the form elements and most browsers (I believe) will tab through them as they flow down the document. I haven’t used “tabindex” for a long time now.

On a similar note (and the main reason for this comment) I just discovered a tabbing “glitch” that happens after the form elements are cloned – and I have a fix for it. The issue is when tabbing through the elements and you press the space bar to trigger the “add section” button, the cloned elements appear but the focus actually remains on the “add section” button. Then, when you press tab again, expecting to jump to the first cloned input, the focus actually jumps to the “remove section above” button, located at the bottom of the screen beneath your cloned area, causing momentary confusion, grief, and a touch of anger for the user – at least it did all that when I was the user testing my forms.

To correct this, add

$(‘#title’ + newNum).focus(); (using the example form)

beneath $(‘#input’ + num).after(newElem); (line 21 of the example script)

This makes the script clone all the specified elements then immediately apply the focus to the newly cloned #title2. Of course, use the ID of the first element that gets cloned, instead (First as it lays on the form, not the script). With the above example form TITLE is first, and in the above example script, FIRST NAME is cloned first. It doesn’t really make a difference for the cloning, but it does for the focusing.

Anyway, hope this helps someone!

Dan

Reply
Tristan Denyer

I removed all the tabindex attributes, so now the form works with the browser and not against it. The focus you suggested works great too. Thanks!

Reply
Josh

Hi, this is fantastic. However, I have one question. I am taking the form and posting to MySQL dbase with PHP. How do I make it so upon cloning, the fields with the same name and ID (i.e. not become Name1, Name2, etc.) ? This way I can turn the fields into an array and post to multiple dbase rows with one submission

Reply
Tristan Denyer

Below, I am referencing the clone-form-td.js file found in the download package, not the line numbers found in the blog post. I tested it and got it to work by replacing lines 16-38 with the following:
[sourcecode language=”plain”]// Title – select
newElem.find(‘.select_ttl’).val(”);

// First name – text
newElem.find(‘.input_fn’).val(”);

// Last name – text
newElem.find(‘.input_ln’).val(”);

// Color – checkbox
newElem.find(‘.input_checkboxitem’).val([]);

// Skate – radio
newElem.find(‘.input_radio’).val([]);

// Email – text
newElem.find(‘.input_email’).val(”);[/sourcecode]
In short, you are removing the first line for .label_ and modifying the second line for the form field so it does not NOT alter the .attr (by removing that part of the JS.) BUT, you will likely want to have the cloned fileds NOT pre-populate the info the user put in the section above, so leave the .val(”); part in place to clone and create blank fields. If this is not a concern, delete all lines 16-38.

Focus will not work since there is no longer a unique ID to hang it on. So, line 42 can be removed too.

Each form section builds a consecutive ID of entry1, entry2, entry3. Leave in place. Do NOT delete .attr(‘id’, ‘entry’ + newNum) from line 11, or else you will not be able to clone past one additional section.

Reply
Zed

Hi.
Maybe a noob question.

But shouldnt I be able to do like this:

$Unit = $_POST[’email_address];
$Unit2 = $_POST[’email_address2];

or is that the wrong name for the newly duplicated field?

Reply
Tristan Denyer

Not noob at all. Not asking is a noob thing.

I think you are looking for “ID2_email_address” — older versions of my plugin did append the number at the end. The first section uses “email_address”, then each cloned section gets ‘ID’ + newNum + ‘ appended before it. (If you prefer to have the sequential numbering come after the name/ID, you could switch the order in the .js file.) After the section has been cloned 4 additional times, you would have the following:
“email_address”, “ID2_email_address”, “ID3_email_address”, “ID4_email_address”, “ID5_email_address” (this naming convention goes for all fields in this form plugin.)
In case you are not using it, I recommend right-clicking the cloned fields and using “inspect element” to see their appended names — viewing source code won’t help here.

Below is the input of the cloned filed:
[sourcecode language=”plain”]<input class="input_email" type="text" name="ID2_email_address" id="ID2_email_address" value="" placeholder="like this: billybob@example.com">
[/sourcecode]
Hope that answers your question. Let me know if it doesn’t.

Reply
carter

hi to all…
wonderful script…
Can I ask one question?
How can I send via mail the data of the form?
I mean data of all forms…not just the first…
example…
I submit 5 forms (limit) and I want to send via mail all data…
How can I do it?
Excuse me for the question but I don’t know very well jQuery
Thanks to all

Reply
Tristan Denyer

Looks like you would need to use the following in the form tag:

See this page for the example code: http://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_mail

But, I haven’t tried this method, and I think it will likely open the user’s email client and ask them to send it. I would suggest you look for a server-side script that retrieves the form inputs, collects them in an email and sends the email to end user. This would depend on your server, so figure out what you are running (PHP, Java, et. al.) and Google around for a script that is compatible.

Reply
carter

thanks for the answer…
I have the script that send mail after control on data…
my problem is that the script send an email with just the first form…
I would to know how to collect all data…
I don’t know if I explain
You have any idea?

Reply
Tristan Denyer

This sounds like an issue with your script. I am unable to answer this for you since I have never hooked this up to a server and performed the task you are looking for. Others may have. And recently one of them was using an array to collect the data. Possibly one of them might be able to add to this thread and help out. I’ll post it on Twitter and LinkedIn to see if anyone there can help.

Reply
carter

Thanks for the answer Tristan…
I solved my problem simply with a loop…
The script the script is done well and allowed me to use this method…
Thanks a lot

Tristan Denyer

Nice! I like how the added section slides into view. Very slick. Thanks for sharing your site with us.

Reply
Baidwan

Hi Tristan Denyer

You did a great job I am using it. It works excellent.
But I am getting problem when I have to insert the data from dynamically created multiple form into mysql using php. Please help if u have the solution or any hint.

Reply
peskat

I’ve been toying with this script for a few days now and it works miracles for duplicating my form. I have a couple of questions though that I can’t seem to figure out, given my inexperience with js and jquery.

Can I avoid duplicating an element inside the form? I have an photo upload field in an edit form that I need to show the previous photo uploaded. I do this with a static img element. When I duplicate the form it duplicates the photo, as it is meant to, even though the new form has no related photo. Is there some way to keep the photo within the form and exclude it from duplication?

I am also using the jqueryui datepicker. I’ve modified the script so it duplicates correctly, but while it maintains localisation, it loses the parameters I pass in the beginning of the page, like changeMonth and changeYear.

Anyway, I really appreciate the great work you’ve done with this, it has saved me a ton of work and those using my page a lot of page loads.

Reply
Tristan Denyer

I’m glad it is (mostly) working for you! As for the image being duplicated, I think it has to do with the fact that this plugin is duplicating the inline form elements input and select and all of their contents. It is important to note that the .val(”) in the js is what tells the duplicate form to clear the input and select when the user adds a section. So, if your image is wrapped inside the label, input tags being duplicated, it too will be duplicated.

That being said, could you place the image inside a textarea field and have the js use .val(”) to clear it when the section is duplicated? You can do some crafty CSS to hide the visual components of the textarea container (or style them to your advantage.) Another option could be to wrap it in a div and assign some js to it—and here is where I am guessing— like $(“#ID2_xxxxxxx .img”).remove();. If you have a max of 5 sections, then you already know the expected IDs of the duplicated field and could add this 4 times to clear the image for the 4 times it is duplicated.

Oh, as I am typing this I realized (that using my suggestion above) when the user duplicates the form a second time it may clear the image preceding it. Either way, you are probably looking for a .remove() (http://api.jquery.com/remove/) or .empty() (http://api.jquery.com/empty/) method that will clear the contents of the img’s parent container. I might look into this in the near future.

As for the datepicker, I am thinking that you are having the same problem Mario had with autotab plugin (see Feb 14th comment above). It seems once the js for the datepicker loads it would need to reload for each section of the form that loads. And this doen’t happen. We guessed ajax would help, but that is out of my league right now.

Reply
peskat

Thank you for your quick reply. I decided to let the image duplicate, but add a class to it and hide it using css. I will try remove and see where it takes me.

As for the datepicker, I had already taken previous comments into consideration, adding a .removeClass(“hasDatepicker”).datepicker().val(”); part to the script so that it reloads it. I just don’t know enough to understand why the duplicates don’t use the parameters like the original. I will look more in the documentation of jqueryui, maybe I’m missing something

Reply
Sami

A lot of thanks, That is very good plugin, But i have some problem,
1. I am include input filed with time-picker (jQuery time-piker), but It cannot working when ‘add section filed’ this block.
2. Currently Two Events (Two Block) then, disable ‘remove section above’.

Reply
Leo

Great post, great tool….

Quick question: How can I duplicate the field values (after the entry section is duplicated) with a button click?

Many Thanks

Reply
Tristan Denyer

If I read this correctly, it sounds like you just need to remove the .val('') part in the JS. There is one for each item. This removes the value when cloned. By removing it, any value the user types in for the field will be duplicated too.

Reply
Leo

Hi Tristan,
Thanks for the reply.
I actually need the fields to be blank initially (no values duplicated) but then have a button which can duplicate them.
Hope you can help.

Reply
Rob

Is there any way to remove fields other than just the one above?

What if you have entered 10 fields and just need to remove the second one without having to remove 3-10 as well?

Makes it a little unfriendly.

Reply
Tristan Denyer

You are right. The ‘remove’ function in this form is really to be used inline. There are other form jQuery plugins out there that allow for the user to remove specific fields at will, regardless of order. And that may be better suited for your needs.

I’m ok with this since I feel the plugin is built for forms being filled out for the first time, and at that moment is when the user will know if they need to remove the form section they just entered or not. I didn’t intend this to be part of an admin area where the user can remove specific sections of a form.

I feel it is likely an edge case that a user will get to #10 and realize they need to remove #2, though it could happen and for those cases I agree: it would suck to have to delete 7 or 8 entries to delete that one. But, the user could just go up to #2 and edit it with the data they intended for #10, instead of deleting it.

Hope that makes sense, and thank you for the feedback.

Reply
Rob

Thanks for the reply.

Do you happen to know any good plugins that would do that? I saw sheepit but it just seemed a little old.

The reason I was asking was that I want to build the fields from data saved in a database and let the user add and delete them at will and then save what’s left to be used on the frontend.

Great work on the plugin though. Best example I could find of how to do anything like this.

Reply
Jonathan Vanasco

Your code has been a life saver for me on a project I have been working on for a client! I am having a small issue I am hoping you can help me with. I have a form with a bunch of JS functions that show or hide certain inputs based upon what you select. That all works great! But once you hit the button to “add zone” which is using your code, the same JS functions do not work. The link to my project is : http://www.purelygeek.com/dev/pexheat/test/jquery/jquery_estimate_request.html

Any help would be awesome! You can see that in my project the functions work great when you are filling out “Zone1” but once you hit the button to create additional zones the functions stop working. and I can’t seem to figure out why.

Reply
Heath

Did you find a solution to this issue? Tristan had recommended a solution that another user had found, but it didn’t seem to work for me.

var url= “http://yourdomain.com/js/nature”+newNum+”.js”;
$.getScript(url, function(){
});

Reply
DJ

Hi. Great plugin. I have a question. How to clear value of or when duplicated. Thank you in advance.

Reply
Tristan Denyer

Look for the .val(”); at the end of the lines in the JS. This clears the value when it is duplicated.

Reply
DJ

I understand, but how to clear value of div or span element where the value of input is displayed. When i clone, the input it reset, but the div and span get the value of the first input.

Reply
Ray

I have a form with fieldsets and could use all the help I can get to get this to add as needed. I would like to start out with just an add with no rows present and gladly reimburse someone for their time.

– – – – – – – – – – – – –

Tristan: If you are someone you know would like to help Ray out with some paid work, contact him at rkomar(at)mac(dot)com.

Reply
Gowtham

I added two drop downlist using this cloned method. When you select some values in drop downlist it would bind data in other dropdown list. but once i select the value the page postbacks and the drop downlist disappears. can you help me in this?

Reply
Lizset

Thank you so much for your demo. It is really helpful. But I have a question. I’m trying to create an application that uses two of this duplicate section. I tried duplicating the code to obtain both sections but that didn’t work. Can you please help me with this? Thanks

Reply
Tristan Denyer

Without seeing the actual code and situation, I am going to have to take a guess here that you are talking about using two sections on the same page or view state. This has come up before with other people trying to do the same thing, and I have yet to get a response from anyone saying they got it working.

Duplicating the code is the right start, I think. More importantly would be to make sure you are using unique IDs for each. You should try appending all IDs and classes on the second one with something like “_x” to ensure there is no conflict, no crossover. Each section would then use its own version of the script. You are doubling the codebase, but it could be a start to see if it would work for your use case.

In some other cases before my answer has been to rerun the script. Another person had a use case where the second form section was created after the script initially ran, so we needed to rerun the script on click of a button.

Let me know if this helps or not.

Reply
Lizset

What you described is what I’m trying to do but using unique ids didn’t work 🙁 . I tried rerunning the script but still can’t get it to work. But thanks for your reply. I’ll keep trying

Reply
Tristan Denyer

Ok. I wish I had the time right now to try and create a demo using 2 sections that can duplicate. Have you tried posting it on Stackexchange to see if someone can help you there? If you do, let me know and I’ll share a link asking for help.

Reply
David

Hi Tristan thanks for this script it works amazing!

I have modifed the script to
newElem.find(‘.input-***’).attr(‘id’, ‘***’ + newNum).attr(‘name’, ‘***[‘+ newNum + ‘]’).val(”);

this allows the results to be displayed as an array making back end integration with databased.

I have one question though. I want to make a dependent dropdown box, so I select one and it allows certain selections of another. I have tried many different options but I can’t get the cloning to work with it correctly. Any suggestions?

Reply
Bianca

Hi Tristan,

That script is awesome. I have used that before in other code that I had and it worked, but now, I want to do four sections like the sign up information (I am using version 0.7) with different information, every section can have more fields. I tried to do, but the clone stuff is not working for the second section, and I have no idea why. If you could help me… thank you so much 🙂 !

Reply
Bianca

Here is the code.
The first section is working!

$(document).ready(function() {
$(‘#btnAddMeas’).click(function() {
var num = $(‘.clonedInput’).length; // how many “duplicatable” input fields we currently have
alert(num);
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.find(‘#label_measures_showas label’).attr(‘for’, ‘showas’ + newNum);
newElem.find(‘#input_measures_showas input’).attr(‘id’, ‘showas’ + newNum).attr(‘name’, ‘showas’ + newNum).val(”);

newElem.find(‘#label_measures_measure label’).attr(‘for’, ‘measure’ + newNum);
newElem.find(‘#input_measures_measure input’).attr(‘id’, ‘measure’ + newNum).attr(‘name’, ‘measure’ + newNum).val(”);

newElem.find(‘#label_measures_value label’).attr(‘for’, ‘value’ + newNum);
newElem.find(‘#input_measures_value input’).attr(‘id’, ‘value’ + newNum).attr(‘name’, ‘value’ + newNum).val(”);

// insert the new element after the last “duplicatable” input field
$(‘#input’ + num).after(newElem);

// enable the “remove” button
$(‘#btnDelMeas’).attr(‘disabled’,false);

// business rule: you can only add 5 names
//if (newNum == 5)
//$(‘#btnAddMeas’).attr(‘disabled’,true);
});

$(‘#btnDelMeas’).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
$(‘#btnAddMeas’).attr(‘disabled’,false);

// if only one element remains, disable the “remove” button
if (num-1 == 1)
$(‘#btnDelMeas’).attr(‘disabled’,true);
});

$(‘#btnDelMeas’).attr(‘disabled’,true);
});

$(document).ready(function() {
$(‘#btnAddClMeas’).click(function() {
alert(“entrei aqui”);
var num2 = $(‘.clonedInput2’).length; // how many “duplicatable” input fields we currently have
alert(num2);
var newNum2 = new Number(num2 + 1); // the numeric ID of the new input field being added
//alert(“entrei aqui1”);
// create the new elemen2t via clone(), and manipulate it’s ID using newNum value
var newElem2 = $(‘#input2’ + num2).clone().attr(‘id’, ‘input2’ + newNum2);
alert(newElem2);
//alert(“entrei aqui2″);
// manipulate the name/id values of the input inside the new element
newElem2.find(‘#label_clmeasures_showas label’).attr(‘for’, ‘clshowas’ + newNum2);
newElem2.find(‘#input_clmeasures_showas input’).attr(‘id’, ‘clshowas’ + newNum2).attr(‘name’, ‘clshowas’ + newNum2).val(”);
//alert(“entrei aqui3″);
newElem2.find(‘#label_clmeasures_measure label’).attr(‘for’, ‘clmeasure’ + newNum2);
newElem2.find(‘#input_clmeasures_measure input’).attr(‘id’, ‘clmeasure’ + newNum2).attr(‘name’, ‘clmeasure’ + newNum2).val(”);
//alert(“entrei aqui4″);
newElem2.find(‘#label_clmeasures_value label’).attr(‘for’, ‘clvalue’ + newNum2);
newElem2.find(‘#input_clmeasures_value input’).attr(‘id’, ‘clvalue’ + newNum2).attr(‘name’, ‘clvalue’ + newNum2).val(”);
//alert(“entrei aqui5”);

// insert the new element after the last “duplicatable” input field
$(‘#input2’ + num2).after(newElem2);
//alert(“entrei aqui6”);
// enable the “remove” button
$(‘#btnDelMeascl’).attr(‘disabled’,false);
//alert(“entrei aqui7”);
// business rule: you can only add 5 names
//if (newNum == 5)
//$(‘#btnAddMeas’).attr(‘disabled’,true);
});

$(‘#btnDelMeascl’).click(function() {
alert(“entrei aqui8”);
var num2 = $(‘.clonedInput2’).length; // how many “duplicatable” input fields we currently have
$(‘#input2’ + num2).remove(); // remove the last element

// enable the “add” button
$(‘#btnAddClMeas’).attr(‘disabled’,false);

// if only one element remains, disable the “remove” button
if (num2-1 == 1)
$(‘#btnDelMeascl’).attr(‘disabled’,true);
});

$(‘#btnDelMeascl’).attr(‘disabled’,true);
});

Measures

Show As:

Measure:

Value:

Clothing Measures

Clothing Show As:

Clothing Measure:

Clothing Value:

Reply
Robert

Thank you so much for publishing this great tool. I am implementing it into my project and it is working flawlessly. I did modify the code a bit so that I duplicate a dropdown/select list and a textbox. The select list gives a list of projects and the text box allows comments for each project. It works flawlessly. I store the values into a dual delimited string that I then put into a hidden field so that I can store in my database.

My question is now that I have the data stored in the database do you have examples on how to repopulate the page from the database, thus creating (i) number of fields to be rendered on the page to be what was origionally submitted/stored? Can you point me in the right direction on how to achieve this?

Thanks

Rob

Reply
Tristan Denyer

Great question and idea. As of yet, I do not have a solution for this. And I have not seen or heard of anyone doing this. Your question did make me think about how a user would go back in and edit what they entered. I guess I assumed the form was a one-way submission appliance and that the person needing to go in and edit what was originally submitted would do so on an admin screen, possibly in a table or rows concept. Obviously that does not apply or work for all cases.

In short, I do not have a solution for you. The form wasn’t originally made to be populated via the database, and also the cloned sections weren’t meant to be anything other that user-initiated. Maybe someone else has an idea or can help?

Reply
amanzshee

how to insert data with different id using php mysql? i tried to used foreach, but i’ve got some error.

Reply
Tristan Denyer

To be completely honest, I have no experience with actually hooking this up to a database. I have always relied on a developer/engineer to hook it up to the backend. I hope to one day figure it out, but for now it is beyond my ability. I recommend reaching out on StackOverflow to see if someone can help you.

Reply
David Evans

Hi, if you modfiy the code to allow for arrays like such
newElem.find(‘.input-apostvariable’).attr(‘id’, ‘apostvariable’ + newNum).attr(‘name’, ‘apostvariable[‘+ newNum + ‘]’).val(”);

you can use

$arraycount = count($_POST[‘apostvariable’]);
for($x = 1; $x <= $arraycount; $x++){
//put post variables here
$topost = $_POST['apostvariable'][$i];
}

hope this helps!

Reply
Daniela

Hellooo! I took the advice and I modified the code, trying to give an id name which can work and insert in the db, but is not working….it just take the last register. What is missing me? Thanks in advance.

Reply
Bilal

Hello dear sir the clone is working perfectly but unfortunately I am unable to get the code where the form is submitted… can you please help in this regards???

I am cloning only first name, last name and email…. how to get all these values in $_post???

Reply
Tristan Denyer

Thanks for asking. Unfortunately while I wrote this plugin I am not able to how to post it to the database since I don’t know how either. I wrote this for a backend engineer that took care of the post, and I have never had the time/chance to learn how. I would recommend checking with Stackoverflow for a good answer to this problem. Or maybe someone here can help out?

Reply
Bilal

i am cloning only first name, last name and email…. how to get all these values in $_post???

Reply
anoncoder

hi,i have copied your code and download the files?(js fils,etc) but i still cant seems to run the whole cloning of form coding. any idea why?

Reply
Michelle

I am trying to add a date field with a date picker inside the cloneable form. It works just fine with the html5 date in Chrome. However I have tried adding various date picker widgets and for some reason, although they work with the initial form, they do not work with the cloned copies. Instead of opening up a date picker it just acts as a textfield. I was wondering if you could tell me what I’m doing wrong. Here is a link to a jsfiddle I set up demonstrating the problem: https://jsfiddle.net/sr0sd74r/

Reply
Tristan Denyer

This seems to be a common problem. I have been asked about datepickers for awhile, and have yet to get one to work. The fact that the html5 date in Chrome works is inspiring. Other devs have tried third party date pickers and it seems none of them work.

I’ve told people to try and rerun the datepicker js when you clone the form since the datepicker DOM element that is cloned comes in after the js was initially run. That is my best guess, and no one has ever come back to me and said they got it working, nor has anyone made a pull request to show a fix for this.

I have not been able to get one to work either, but will look into the html5 date as a stopgap. Let me know if this helps or you get it working. Feel free to hit me up on the Github repo for the plugin.

Reply
Michelle

I have tried several different date pickers and tried re calling the date picker scripts from several different places and nothing has worked. I am out of time on this but I may try to work on it again in the future. Thanks for your help. This was an invaluable help to me even though I couldn’t get the date picker working.

Reply
Celene

Hello,
How would you handle the submission of the cloned form. In your demo every time the user click “add section” a new Entry Form dynamically appear. So how would you submit each Entry? In other words, how would you submit the all the forms?

thanks
celene

Reply
Tristan Denyer

All of the cloned forms are inside a single form tag that posts to your server. I do not have instructions on how to post to your server since I don’t have experience in connecting forms to servers. My experience ends at the form’s HTML, CSS and JS.

I recommend searching on Stackoverflow for how to connect your form to your server config.

Reply
Ron

This is an awesome bit of coding that has helped me immensely! I am wondering if you could assist with another level of duplication though. Is it possible to duplicate a field within a duplicated section. In other words, I am building a form builder in which there can be between one to several questions within each section. So, at present, I have enabled the ability to create a Section 2, Section 3… but I am unable to clone the “next Question” field within any section after section one. Any assistance would be much appreciated.

Thanks!

Reply
Tristan Denyer

Possible? I think so, but have never had luck with it—also haven’t spent a lot of time working on it. In a sense, you are nesting the thing the JS needs to duplicate. So, the way the script works right now, nested elements that can be duplicated independently of the parent would need their own unique script.

The real problem lies in the fact that ‘next question’ in Section 1 has to have a unique ID, say “nextQuestion”. When duplicated, the ‘ID’ + newNum part of the script appends a sequential number to it. Nothing new there, but where getting to the problem.

When you duplicate the parent section for ‘next question’, you will have to ensure it gets duplicated with a unique ID, otherwise when the user clicks ‘next question’ trying to append a new question, the script will see 2 identical IDs of “nextQuestion”. So, you manage to get Section 2’s ID of “nextQuestion” to be “nextQuestion2”. Problem is that the script is still looking for “nextQuestion”. You would now have to write another duplicating script looking for “nextQuestion2”, and so forth for every possible unique ID a “nextQuestion” could have. That’s not scalable and just bad on so many levels.

This is where I have gotten stuck on this and have not been able to find a way to write the script to allow the child elements to be cloned independent of the parent well into the second and third sections. Not much help, unfortunately. Maybe I am overthinking this? Let me know what you think, and if you are able to crack it.

Reply
Ron

Tristan – thanks so much for your response. While it may not be optimal, my solution was to basically create a 3-staged form in which base info on the first form, questions on the second (via cloned elements) and on the third and final stage, values for the elements created in the 2nd if they require a predetermined value. (.e.g. if the answer isn’t simply a text, textarea or some pre-determined boolean values).
1st stage – tablename and sections are created (since sections are unknown, I use a simple duplicate to create the desired number of sections.
2nd stage – On submit, title of newly created form is entered in mysql “forms” table, section titles inserted into form_structures table based on inserted Id. Simultaneously, the user is presented with a new “cloneable” form from which they can create the questions and choose their section in which they are to appear.

Now my problem is…getting the randomly created questions into mysql. Dealing with one checkbox was easy by simply creating an array (e.g. name[]), but when you have a variable number of inputs and varying types of fields of which to populate, it becomes more complex. The biggest issue is dealing with the dynamically added _1_name, _1_id, _2_name, _2_id….

Just not sure how to work with this as yet. And based on my google queries, not many people are. If I find some answers, I’ll share.

Thanks again for solving a big part of the puzzle though!

Reply
Christopher Arter

Do you think this would work well with an AJAX call to WooCommerce in WordPress? I’m going to attempt to use it as a form to create posts, each one of which would be a charge or item in the basket. Think this would work well for that?

Reply
Tristan Denyer

To be honest, I have no idea. It should, since it is only the front-end for the form and is not limited to a specific platform. I would reach out to WooCommerce to see if it would work.

Reply
Jonathan

Hey Tristan, I have quick question I hope you can help me with. Basically what I want to do is also clone the onkeyup and onkeydown section in my input on your clone JS file. I have a function on my main page that replaces any instance of an ampersand with “and” instead because this ultimately gets converted into an XML file and imported into excel which does not allow: [html]&amp;[/html]

[html]// New Zone – text
newElem.find(‘.label_fn’).attr(‘for’,’Zone_Name’ + newNum);
newElem.find(‘.input_fn’).attr(‘id’,’Zone_Name’ + newNum).attr(‘name’, ” + ‘Zone_Name’ + newNum).val(‘Zone ‘ + newNum);[/html]

Reply
Tristan Denyer

I assume you are asking because it is not working for you? I see the code you pasted, and (without seeing your HTML) it appears to be in order and similar to the other code I wrote.

Keep in mind that when you clone a section of the form that has JS specific to that section (like a datepicker, or other functionality) when you clone the form it will likely NOT work. Thing is, that cloned DOM element wasn’t there when the JS was first initialized and is likely not being seen. OR, in some cases it is a duplicate of some other DOM element and the JS gets applied to both, wrongly.

If you have a working example I can see (or send me files that work locally), I can try and look at it a bit closer.

Also, let me know what you expect it to do and what is not working.

Reply
Chris Arter

Hi Tristan, thanks a TON for doing this tutorial. It’s helped me with a project 10 fold.

So I’m struggling with one component of what I’m trying to build and maybe you could point me in the right direction. I’m really new to jQuery.

I’m using this form to duplicate fields, but I’m not sure how to approach taking each set of fields and sending them to a php handler to turn those into posts per set of fields (in wordpress). I’d do this via ajax post call on submit. I’m comfortable with the PHP handler side, but how to send those ‘sets’ of data per duplicated section to the handler is where I’m at a loss. How would you approach it?

Thanks again!

Reply
Tristan Denyer

Glad this helped! To be honest, my skills with forms end here. I have never wired up a form to actually post to a data base. I get asked this a lot—so you are not alone—and I have yet to find the time to learn how.

Tutorials for WordPress tend to be in abundance. There’s also a Slack community by the WordPress organization that may be of help.

Wish I could be of more help, I just never got that far in my learning.

Reply
Chris Arter

No worries Tristan, this help with the DOM duplication has been more than enough help. I actually figured out how to do it last night, so for anyone reading this attempting to do something similar, just put the $_POST[] variables in an array, then run a foreach on it and use wp_insert_post.

And thanks for the link, I’m going to check that out now.

Reply
Milan

Hello, i want to thank you for this plugin, helped me a lot, but i have an issue, and if you or someone would help me it would be great. I’m working on a project and i’m using this plugin, working like a charm, but inside form i need another button that adds another input field as a answer options. Managed to make it work on a first form but cant make it work on cloned ones.

Something like this 🙂

https://tristandenyer.com/demos/dynamic-form-bootstrap-3-3-4-multiple.html

…but it needs to work in cloned sections.
Thanks

Reply
Tristan Denyer

I get this question a lot, but haven’t been able to A) get it working, and B) hear back from anyone that got it working.

The problem I think that is happening is the cloned form elements were created after the the JS ran. So, anything inside it that requires JS (like a JS datepicker or another JS cloning function) won’t work because its ODM elements were created after the initial JS ran. This may be solved (in a heavy way) by using React, Ember or Angular, or in a lightweight way by asking the JS to rerun when the user click the ‘add’ button.

If you can get it to work, would love to know how you did it! In fact, a lot of people would.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *