Duplicate form sections with jQuery - Improved

admin Friday May 27, 2016

Based on David Carr's excessively simple technique to duplicate form sections using JavaScript, here is my enhanced but still minimalist take, adding support for:

  1. select multiple
  2. starting the form with several sections already
  3. easy backend usage

This changes indices so they start at 0. Image Duplicate Form Sections

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

//define counter
var sectionsCount = jQuery('div.section:last').data('number');

function incrementIdentifier(id, sectionsCount) {
	if (id.substr(-1) == '0') {
		id = id.substr(0, id.length - 1);
	return id + sectionsCount;

//add new section
$('body').on('click', '.addsection', function() {
	//loop through each input
	var section = template.clone().find(':input').each(function(){
		//set id to store the updated section number
		newId = incrementIdentifier(this.id, sectionsCount);
		//update for label
		$(this).prev().attr('for', newId);
		//update id
		this.id = newId;
		var baseName = this.name;
		var array = false;
		if (baseName.substr(-2) == '[]') {
			array = true;
			baseName = baseName.substr(0, baseName.length - 2);
		baseName = incrementIdentifier(baseName, sectionsCount);
		if (array) {
			baseName = baseName + '[]';
		this.name = baseName;
	//inject new section
	return false;

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

As a bonus, the PHP function I quickly crafted to ease processing the resulting $_REQUEST:

 * Treat $_REQUEST when working with duplicate-form-sections.js
 * $_REQUEST['numberedParameters'] contains the base name of the parameters to be converted into arrays
 * $_REQUEST['lastSection'] is the number of the last section (the number of sections minus 1)
 * Alters neither $_GET nor $_POST
 * @author Philippe Cloutier
 * @license MIT
 * @return boolean false on failure
function numberedParametersToArrays() {
	if (! isset($_REQUEST['lastSection'])) {
		return false;
	$numberedParameters = $_REQUEST['numberedParameters'];
	$lastSection = $_REQUEST['lastSection'];
	foreach ($numberedParameters as $numberedParameter) {
		$_REQUEST[$numberedParameter] = array();
		for ($i = 0; $i <= $lastSection; $i++) {
			if (isset($_REQUEST[$numberedParameter . $i])) {
				$_REQUEST[$numberedParameter][] = $_REQUEST[$numberedParameter . $i];
			} else {
				$_REQUEST[$numberedParameter][] = array();
			// We could unset the numbered parameters.
	return true;

And here is an adjusted usage example:


<div id="sections">
  <div class="section" data-number="0">

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

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

            <select name="friends1[]" id="friends1" size="2" multiple>

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


<p><a href="#" class='addsection'>Add Section</a></p>
<input type="hidden" name="numberedParameters[]" value="firstName">
<input type="hidden" name="numberedParameters[]" value="lastName">
<input type="hidden" name="numberedParameters[]" value="friends">
<input type="hidden" name="lastSection" value="0">

Note that there are similar solutions elsewhere. I am not saying this one is better than these.

Permalink: https://philippecloutier.com/blogpost47-Duplicate-form-sections-with-jQuery-Improved