Dynamic multi form on same page with jQuery and PHP

This is a little demo of a small app that allow us to have several forms displayed on the same page, organized by sections, a static multiform can be easily created by putting the form contents on divs and hiding them, then when the user clicks on a specific section we hide the previous div, and show the new one, we can wrap it up everything inside a big form, and submit that.

The approach I did for having this same functionality allows me to:

  • Save each section form before editing a new one
  • Change any form inputs depending on received data
  • Validate in the front and backend each section

The main disadvantage is that for each section I’ll do an ajax call, to submit and retrieve the form.

The first thing I did was to write the main html layout I did a simple 2 column layout to use the left block as a form navigator and the right block to show the actual form.

<div class="left_block_box">
	<div class="left_block_title">
		 Form Steps
	</div>
	<div id="edit_step_box">
		<table width="100%" cellspacing="0" cellpadding="0" border="0" style="font-size: 11px;" id="stepTable">
		<tr class="stepSelected">
			<td class="formStep">
				 Name
			</td>
			<td class="stepEdit">
				<span id="formstep1" class="pointer placeEdit">Edit</span>
			</td>
		</tr>
		<tr>
			<td class="formStep">
				 Address
			</td>
			<td class="stepEdit">
				<span id="formstep2" class="pointer placeEdit">Edit</span>
			</td>
		</tr>
		<tr>
			<td class="formStep">
				 Interests:
			</td>
			<td class="stepEdit">
				<span id="formstep3" class="pointer placeEdit">Edit</span>
			</td>
		</tr>
		</table>
	</div>
</div>

I’ve used a table so I can navigate more easily the DOM with jquery, but this can be changed an ul and it will work the same, the next thing I wrote was the other column wrapper the right block which will holde the actual form retrieved from the server.

<div class="right_block_box">
	<div class="right_block_title" id="formTitle">
		 Form 1
	</div>
	<div class="multiform_part">
		 Aqui va la forma
	</div>
	<div id="form_step_nav_wrap">
		<div id="form_step_nav">
			<div id="form_step_left">
				<input type="button" value="Previous Step" id="prevStepBtn"/>
			</div>
			<div id="form_step_right">
				<input type="button" value="Next Step" id="nextStepBtn"/>
				<input type="button" value="Preview Data" style="display: none" id="previewBtn"/>
			</div>
		</div>
	</div>
</div>

Once I had my basic layout I started with the javascript functionality, the first thing was to create a function that allow me to move from one form to another, passing current form values to the calling script and displaying the new form.

function selectStep(step) {
	var thisStep = $(step).children().attr('id');
	//get current form data to be passed later
	var curr = $(".stepSelected").children(':eq(1)').children().attr('id');
	var formData = $("#form_"+curr).serialize();
	//add class to selected step 
	$("#stepTable tr").removeClass('stepSelected');
	$(step).parent().addClass('stepSelected');
	//put name of step that is going to be edited 
	$("#formTitle").text($(".stepSelected :eq(0)").text());
	$(".multiform_part").html("Loading...");
	//send data to php, and draw new form
	$.post('processForm.php', {
		step: thisStep, saveData: curr, formData: formData
	}
	,function(data) {
		//draw new form
		$(".multiform_part").html(data);
	}
	);
}

This was easy, then I just binded a click event to each step

	// handle the edit  link on each step
    $(".stepEdit").each(function(index){
        $(this).click(function(e){
            selectStep(this);
            }
        );
    });

And now I have a functional multiform pane, that gets its form from php, the backend was also ver simple to make:

< ?php
session_start();
$step = $_REQUEST['step'];
$formData = $_REQUEST['formData'];
function save($step, $data) {
	//$_SESSION[$step] = $data;
	$fields = explode('&',$data);
	foreach ($fields as $field) {
		$keyVal = explode('=', $field);
		$key = urldecode($keyVal[0]);
		$val = urldecode($keyVal[1]);
		$_SESSION[$step][$key] = $val;
	}
}
if ($formData) {
	$formStep = $_REQUEST['saveData'];
	save($formStep, $_REQUEST['formData']);
}
if ($step) {
	switch ($step) {
		case 'formstep1':
					$html = <<<FORM
					<form id="form_{$step}" name="form_{$step}">
					<fieldset>
		    <legend>Personal information</legend>
		    <div class="fm-req">
		      <label for="fm-firstname">First name:</label>
		      <input name="fm-firstname" id="fm-firstname" type="text" value="{$_SESSION[$step]['fm-firstname']}"/>
		    </div>
		    <div class="fm-opt">
		      <label for="fm-middlename">Middle name:</label>
		      <input id="fm-middlename" name="fm-middlename" type="text" value="{$_SESSION[$step]['fm-middlename']}"/>
		    </div>
		    <div class="fm-req">
		      <label for="fm-lastname">Last name:</label>
		      <input name="fm-lastname" id="fm-lastname" type="text" value="{$_SESSION[$step]['fm-lastname']}"/>
		    </div>
		    </fieldset>
 
 
		FORM;
		echo $html;
		break;
		case 'formstep2':
					$html = < <<FORM
					<form id="form_{$step}" name="form_{$step}">
		<fieldset>
		<legend>Address </legend>
		    <div class="fm-opt">
		      <label for="fm-addr">Address:</label>
		      <input id="fm-addr" name="fm-addr" type="text" value="{$_SESSION[$step]['fm-addr']}"/>
		    </div>
		    <div class="fm-opt">
		      <label for="fm-city">City or Town:</label>
		      <input id="fm-city" name="fm-city" type="text" value="{$_SESSION[$step]['fm-city']}"/>
		    </div>
		    <div class="fm-opt">
		      <label for="fm-state">State:</label>
		      <input id="fm-state" name="fm-state" type="text" value="{$_SESSION[$step]['fm-state']}"/>
		    </div>
		    <div class="fm-req">
		      <label for="fm-zipcode">Zip code:</label>
		      <input id="fm-zipcode" name="fm-zipcode" type="text" value="{$_SESSION[$step]['fm-zipcode']}"/>
		    </div>
		    </fieldset>
 
		FORM;
		echo $html;
		break;
		case 'formstep3':
					$html = < <<FORM
					<form id="form_{$step}" name="form_{$step}">
		<fieldset>
		<legend>Interests </legend>
		    <div class="fm-opt">
		      <label for="fm-int1">Interest 1:</label>
		      <input id="fm-int1" name="fm-int1" type="text" value="{$_SESSION[$step]['fm-int1']}"/>
		    </div>
		    <div class="fm-opt">
		      <label for="fm-int2">Interest 2:</label>
		      <input id="fm-int2" name="fm-int2" type="text" value="{$_SESSION[$step]['fm-int2']}"/>
		    </div>
		    </fieldset>
 
		FORM;
		echo $html;
		break;
		case 'getAllData':
					echo '<h3>Saved Data</h3>';
 
		print_r($_SESSION);
 
		break;
	}
}
?>

Finally I’ve added some css styles to make it “pretty” and add some other js functionality to navigate back and forth.

You can checkout the working solution here, or get the files here this demo saves user data in session, and the session is destroyed each time you load the index page.

16 thoughts on “Dynamic multi form on same page with jQuery and PHP

  1. At the end of the post there are 2 links to view this implementation working or to get the entire project.

    You can checkout the working solution here, or get the files here this demo saves user data in session, and the session is destroyed each time you load the index page.

  2. Hi I changed the form to send email with the data but how do I call the function?

    Please help. It is not submitting it is just viewing the data.
    thanks

  3. you can use the $_REQUEST['step'] variable to see if the user has clicked on the “send email”, then just pull the data stored in your session and send the email

  4. Yes you only need to modify the javascript a little to check uncheck the radio button, if you want to implement something with checkboxes and start marking them as you enter data you also need to handle this when the .stepEdit element is clicked, I did a quick sample of this working with radio buttons here http://ivanvillareal.com/samples/multiform_radio/ you need to take care of setting the styles of the tr if thats what you are using, this sample doesn’t take care of that so if you click on the next button the tr style will not be updated, but it will give you an idea of how to implement this.

  5. Whoops, actually I meant is there a way to use this with forms that have checkboxes, radio buttons and drop down selection inputs, rather than just text boxes.

  6. It does look like it keeps the data that was chosen, but the checkboxes and radio boxes are cleared if the section is clicked on.

  7. Thanks, in fact your technique of multi-step form helped me a lot. However I want to be able to upload a file i.e. image and be able to retrieve the values such as $_FILES["userfile"]["name"] … etc.

  8. Thank you, the technique of multi-step form helped me a lot.
    I wish I had Quach suggestion to validate the form fields before you go ahead to the next step.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>