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">
  2.  
  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>
  13.  
  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>
  18.  
  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(){
  4.  
  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
  9.  
  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. });
  18.  
  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>
  18.  
  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. }
  13.  
  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] => jeremy@jdmweb.com
  21. ),
  22. [2] => Array (
  23. [fname] => Steve
  24. [lname] => Jobs
  25. [email] => steve@apple.com
  26. )
  27. )

Conclusion

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>

    Regards.
    Jeremy

  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 jQuery.live() 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?

    Thanks!

  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
    y.handle

    Thank you!

Leave a Reply

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

Other Useful Resources

How to integrate the new Twitter api (1.1) in php illustration

On October 11th 2012, Twitter introduced some major changes in its API following its plans to clean things up deeply. As is explaining the twitterapi account they have for example shut down or limited access to some of their data and resources. So if you've noticed that some Twitter functionalities you are using on your site are not working any more, you may have to check a few things. In this article written on NOE interactive's blog, you'll learn what has concretely changed, and you'll be able to follow a few steps to get your Twitter feeds back.

Read more
Standardizing development environments with Vagrant illustration

This is the first article of a series in which we'll explain our development process industrialisation. We'll describe how we went from a team of individuals doing things together but artisanally, to a more industrial and qualitative approach. This first topic talks about how we standardized our development environments with Vagrant.

Read more
jQuery FancyBox plugin illustration

The FancyBox is one of the plugin that I like the most. It's so easy to use and renders really nicely, especially with images. It's a Mac like zooming tool that you can customize quite well and really looks amazing. Source and © Janis Skarnelis

Read more
@Afup_Mtp @DuaelFr Ha ha cool Edouard. Tu seras en terrain connu en plus 😉.15 Nov / 17:39