Javascript, Demos, Tutorials

Duplicate form sections with jQuery

When working with forms it can be incredibly useful to duplicate parts of the form, for instance when creating invoices the line items span multiple lines being able to add new lines as needed.

This tutorial demonstrates taking a div and cloning everything inside.

To start I have this folder structure:

/index.html
/js/jquery.js
/js/app.js

jquery.js contains version v1.11.3.
Inside index.html include the js files:

<script src="js/jquery.js"></script>
<script src="js/app.js"></script>

index.html

A div with an id of sections wraps the elements, the div with a class of sections will be cloned every time the add section link is pressed.

The for labels and id’s in the input’s will end with a number for each new section this ensured the id is always unique. To remove a section another a link is used the important part is the class called remove, when clicked will call a js function inside app.js.

<form>

<div id="sections">
  <div class="section">
    <fieldset>
        <legend>User</legend>

        <p>
            <label for="firstName">First Name:</label>
            <input name="firstName[]" id="firstName" value="" type="text" />
        </p>

        <p>
            <label for="lastName">Last Name:</label>
            <input name="lastName[]" id="lastName" value="" type="text" />
        </p>

        <p><a href="#" class='remove'>Remove Section</a></p>

    </fieldset>
  </div>
</div>

<p><a href="#" class='addsection'>Add Section</a></p>

</form>

app.js

First define the template this is the main div with an id of sections. Using clone to clone the first section division, this ensures new sections originate from the original section. Also define a counter to be used for all incrementing the for labels and id’s.

//define template
var template = $('#sections .section:first').clone();

//define counter
var sectionsCount = 1;

Next when a link is pressed inside the body element with a class of addsection activate this function.

The counter is increased the each input is looped through, the for lable and id’s have the same name as the original section. They are changed by assigning them the newId variable. Finally the new section is injected to the end of the sections div.

//add new section
$('body').on('click', '.addsection', function() {

    //increment
    sectionsCount++;

    //loop through each input
    var section = template.clone().find(':input').each(function(){

        //set id to store the updated section number
        var newId = this.id + sectionsCount;

        //update for label
        $(this).prev().attr('for', newId);

        //update id
        this.id = newId;

    }).end()

    //inject new section
    .appendTo('#sections');
    return false;
});

To remove an existing section a link with a class of remove inside the sections div should be clicked. First fade out the container the 300 sets the speed of the fade. The section is inside of 2 devs they both need to be removed, this is done using parent() twice then call empty.

//remove section
$('#sections').on('click', '.remove', function() {
    //fade out section
    $(this).parent().fadeOut(300, function(){
        //remove parent element (main section)
        $(this).parent().parent().empty();
        return false;
    });
    return false;
});

Complete file:

//define template
var template = $('#sections .section:first').clone();

//define counter
var sectionsCount = 1;

//add new section
$('body').on('click', '.addsection', function() {

    //increment
    sectionsCount++;

    //loop through each input
    var section = template.clone().find(':input').each(function(){

        //set id to store the updated section number
        var newId = this.id + sectionsCount;

        //update for label
        $(this).prev().attr('for', newId);

        //update id
        this.id = newId;

    }).end()

    //inject new section
    .appendTo('#sections');
    return false;
});

//remove section
$('#sections').on('click', '.remove', function() {
    //fade out section
    $(this).parent().fadeOut(300, function(){
        //remove parent element (main section)
        $(this).parent().parent().empty();
        return false;
    });
    return false;
});

 

David Carr

David Carr

For the past 12 years, I’ve been developing applications for the web using mostly PHP. I do this for a living and love what I do as every day there is something new and exciting to learn.

In my spare time, the web development community is a big part of my life. Whether managing online programming groups and blogs or attending a conference, I find keeping involved helps me stay up to date. This is also my chance to give back to the community that helped me get started, a place I am proud to be apart of.

Besides programming I love spending time with friends and family and can often be found together going out catching the latest movie, staying in playing games on the sofa or planning a trip to someplace I’ve never been before.