Form Cloning jQuery Plugin

Building dynamic forms is a task that a lot of web developers will have to do at some point. By dynamic I mean forms that change based on what the user inputs.

A basic example of dynamic forms, are those that allow the user to add the same group of information several times. For example, an attendance form, where you can add several persons, a booking form where you can add several tickets, a membership with several users, a media page with several pictures or videos and so on, the possibilities are countless.

In order to facilitate the development of such forms, I created a little plugin, that allows you to dynamically clone a specific set of information that will be repeated. So if you ever searched a way of cloning forms, fieldsets or groups of input, this could really be helpful.

Thank You for Downloading

I'm glad that you found my work useful. If you did, it might help some other people too. So why not helping me spread the word with a tweet? You could also buy me a coffee to thank me for my code and explanations if you prefer ;).
I hope you'll enjoy your download. Regards. Jeremy.

How to setup

Plugin Inclusion

In order to use the plugin, you'll need to include the jQuery library, and the plugin file. This plugin being very small, you might prefer to copy its code inside one of your existing js file (it will save you the need to load an external file). Otherwise, just include the files as shown:
  1. /** jQuery Inclusion **/
  2. <script type="text/javascript" src="Path_to/jQuery.js"></script>
  3. /** Plugin Inclusion **/
  4. <script type="text/javascript" src="Path_to/jquery.formclone.js"></script>

The Form Markup

Then you can prepare your form markup. There are only two simple thing to check in order to make the plugin work. First, you need to make sure that the elements you want to clone are inside a container (a div, a span, a fieldset or whatever you want), and add to this container a specific class, for example clonable. This class will later on be used to setup the plugin with your form. The second thing to do is to add a starting number to the name of every element that is going to be cloned, for example, name='firstname_1', name='lastname_1' and so on. By doing so, the plugin will automatically increment every name counter as you add more elements. After you have done those two things, the form markup is ready to be connected to the plugin. The only thing you are missing by then is a 'clone me' button, that will generate a new clone when clicked. It has been added on line 16 of the following code:
  1. <form id="cloningdemo" action="/resources/formclone" method="post">
  3. <fieldset class="clonable"> //Add the class clonable to the element to be cloned
  4. <legend>User Details</legend> //Then add your elements
  5. <div class="regrow">
  6. <label>First Name:</label>
  7. <input type="text" name="fname_1" />//Each input must have a starting number
  8. </div>
  9. <div>
  10. <label>Last Name:</label>
  11. <input type="text" name="lname_1" />//Each input must have a starting number
  12. </div>
  14. <div id="formbuttons" class="regrow">
  15. <input type="button" class="button" id="clonetrigger" value="Clone" />
  16. <input type="submit" class="button" id="clonesubmit" value="Submit" />
  17. </div>
  19. </form>

The jQuery Setup

As we have just said, we want to clone our form when the user hits a specific button or link, which in our case, is the button #clonetrigger. We therefore bind the cloning to the click event of this button, as you can see line 5 of the following code. On line 6, just write the name of the class you have used in your form (here .clonable). Line 7 and 8, the plugin works out what the number of the next clone is going to be, you can specify your own if you want. On line 10, we specify that the first element which has your class, is the element to be cloned. Lines 12 and 13, you can specify two options in order to customize where you want to insert the newly generated clone in your DOM. The first option allows you to target a specific element on the page, it could be the id of a specific div for example. The second element allows to specify where you would like to insert your new clone compared to this element, (before it, after it, within it...) It could therefore be any jQuery manipulation method you want (after, before, append, prepend, replaceWith and so on). And finally, line 14, you can pass a limit. If this limit is set, the plugin will not generate more clones than this number. If it's set to 0, it is ignored.
  1. <script type="text/javascript">
  2. //The jQuery Setup
  3. $(document).ready(function(){
  5. $("#clonetrigger").click(function(){
  6. var yourclass=".clonable"; //The class you have used in your form
  7. var clonecount = $(yourclass).length; //how many clones do we already have?
  8. var newid = Number(clonecount) + 1; //Id of the new clone
  10. $(yourclass+":first").fieldclone({//Clone the original elelement
  11. newid_: newid, //Id of the new clone, (you can pass your own if you want)
  12. target_: $("#formbuttons"), //where do we insert the clone? (target element)
  13. insert_: "before", //where do we insert the clone? (after/before/append/prepend...)
  14. limit_: 4 //Maximum Number of Clones
  15. });
  16. return false;
  17. });
  19. });
  20. </script>

Extra: Generated Code

If you are wondering what the code the plugin generates looks like then you should know that it is really simple. Based on your form markup composed of the elements you want clone and each of them having a number, the plugin will generate exactly the same markup for each clone, the only difference being the number, which is incremented with every clone. For example, after one clone, the generated clone for the demonstration looks like this:
  1. //Original Fieldset
  2. <fieldset class="clonable">
  3. <legend>User Details</legend>
  4. <div class="regrow">
  5. <div class="regrow">
  6. <label class="inside">First Name:</label>
  7. <input class="text" name="fname_1" type="text">
  8. </div>
  9. <div class="regrow">
  10. <label class="inside">Last Name:</label>
  11. <input class="text" name="lname_1" type="text">
  12. </div>
  13. <div class="regrow">
  14. <label class="inside">Email:</label>
  15. <input class="text" name="email_1" type="text">
  16. </div>
  17. </div>
  19. //Cloned Fieldset
  20. <fieldset class="clonable">
  21. <legend>User Details</legend>
  22. <div class="regrow">
  23. <div class="regrow">
  24. <label class="inside">First Name:</label>
  25. <input class="text" name="fname_2" type="text">
  26. </div>
  27. <div class="regrow">
  28. <label class="inside">Last Name:</label>
  29. <input class="text" name="lname_2" type="text">
  30. </div>
  31. <div class="regrow">
  32. <label class="inside">Email:</label>
  33. <input class="text" name="email_2" type="text">
  34. </div>
  35. </div>
As you can see it automatically increments the number of every input name. We'll now see how to get the data back easily on the server side once you submit your form.

Extra: How to get the data on the server side?

All the posted values have a name, which is based on the same pattern (as it has been cloned from the same source). We can then use a very simple loop on the server side to structure our data under a form that will be handy to work with:
  1. if (!empty($_POST)) { //The values have been posted
  2. $elements = array();
  3. foreach ($_POST as $key => $val) { //For every posted values
  4. $frags = explode("_", $key); //we separate the attribute name from the number
  5. $id = $frags[1]; //That is the id
  6. $attr = $frags[0]; //And that is the attribute name
  7. if (!empty($val)) {
  8. //We then store the value of this attribute for this element.
  9. $elements[$id][$attr] = htmlentities($val);
  10. }
  11. }
  12. }
  14. //In our demonstration, the array elements would now contain the following structured data:
  15. print_r($elements);
  16. returns:
  17. [1] => Array (
  18. [fname] => Jeremy
  19. [lname] => Desvaux
  20. [email] =>
  21. ),
  22. [2] => Array (
  23. [fname] => Steve
  24. [lname] => Jobs
  25. [email] =>
  26. )
  27. )


This very simple plugin completely removes all the headaches that are involved when you are looking at designing a similar solution. Its dynamic approach doesn't make it too markup dependent so it can work with any form. What do you think of it? Can you think about a way of improving it in any way? Do you find it useful? Let me know your thoughts via the comments.

11 Responses to Form Cloning jQuery Plugin

  1. @jdmweb. Does this support dynamic populating of values perhaps from a json object?

  2. @Jas.

    The plugin doesn't support it as such, but once the clone has beem created, you can populate it from the javascript event, (cf the javascript setup right after line 15, before return false ).

    Right here, you can load your json object, and load its values inside the clone, with something like:
    <code>$(yourclass+":last input[name=yourinput]").val(yourjson.yourval)</code>


  3. First. I think it would be a great idea to be able to automatically add Delete button to each clone.
    Second. Does your plugin also clone event listeners, connected to cloned elements?

  4. think you for this script, but how i can recuparate the total number of clone that i have choice, thx

  5. Replying to myself. One should add DELETE button by hands.
    The events should be bound by method - is is a great solution. Also we can bind DELETE button behavior through this.

  6. By hands, helmus27, by hands...

  7. Bonjour, j'essaie d'utiliser ce plugin sur un formulaire contenant des boutons radio à cloner mais sur internet explorer, malgré le changement d'attribut name de ces boutons radio à chaque clonage, ils restent liés. Quand on en sélectionne un, tous ceux des clones précédents se décochent aussi comme s'ils avaient tous le même attribut name. Merci d'avance pour ton aide.

  8. hi. just wondering if there is a way to select the number of fieldsets to be cloned from a value in a drop down list?


  9. Where is jquery.formclone.js?
    This page seems to be dependant on jquery-1.js, general.js, jquery_002.js and formclone_setup.js, am I missing something

  10. @adrigen. Downward arrow. Got it.

  11. Hi, Hi have an error when I hit the button for clone. The error is this:

    Uncaught TypeError: Cannot read property 'length' of undefined jquery.cloneform.js:51
    $.fn.fieldclone jquery.cloneform.js:51
    (anonymous function) main.js:18
    x.event.dispatch jquery-2.0.3.min.js:5

    Thank you!

Leave a Reply

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

Other Useful Resources

My Favourite MYSQL functions illustration

For the previous years I've been trying to point out the areas of my workflow that were taking most of my time to try to optimise them.

One of these areas was database interactions meaning the famous 'SELECT', 'INSERT', 'UPDATE' and 'DELETE' statements. When I was still discovering PHP, I spent far too much time hard coding every single database query. It was time consuming, but also very annoying.

Then, for a project, I discovered Zend, a powerful PHP framework. I loved the way it handled the queries, by having a database class with predefined methods for each interaction. The only problem was that Zend is far too bulky and complicated for simple projects.

After investigating if there were easier ways of achieving the same results, I am presenting here today a list of my favourites mysql functions, with their brief description and how you can use them. I hope that it will save you time in your future developments like it did for me.

Read more
Using Composer and Satis to handle private php repositories illustration

Composer is an awesome and powerful tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them, and their respective dependencies for you. To make your own libraries or packages usable by composer users, you need to declare them towards composer. When the package is public, less steps are required. You could host your repository online on GitHub for example, then declare it towards the index for example. When the repository is private, it's a bit trickier, and I spent some time figuring it out, so here's a little feedback on my attempts.

Read more
Retour sur Blend Web Mix 2015 illustration

Blend Web Mix, c'est la conférence Lyonnaise du Web. C'est une chance d'assister à des des conférences enrichissantes et motivantes, de rencontrer des gens intéressants, le tout dans le cadre toujours très agréable de la cité internationale. Cette année encore, l'édition a été riche en enseignements. Retour sur les conférences auxquelles j'ai assisté, et ce que j'ai pu en retirer.

Read more
RT @lemouvementinfo: #Montpellier « Le Vélo au cœur des élections municipales à Montpellier » Nouvelle « manifestive » ce dimanche 10 novem…08 Nov / 09:28