Forum Moderators: coopster

Message Too Old, No Replies

Multi-page forms

         

millyre

12:36 pm on Feb 17, 2006 (gmt 0)

10+ Year Member



Hi,

another question to a common problem that seems to have many solutions.

I'm going to implement a multi-page form, and am looking for the best and robustest solution. I've looked briefly at HTML_QuickForm_Controller, but I don't want to use PEAR/quickform

What I'm thinking of doing is keeping the state ($array_state) of the form either in a hidden field or in a session variable.

Upon receiving a POST, the script merges $_POST with $array_state

$array_state = unserialize($_POST['state']);
OR
$array_state = $_SESSION['state'];

$array_state = array_merge($array_state, $_POST)
- replacing values of existing fields in the array, if any

Then, outputting the state in hidden field as mentioned
<input type="hidden" name="state" value="<?=htmlspecialchars(serialize($array_state))?>

I've seen others putting *each value* in separate hidden fields, but this seems cumbersome to me, when serialize() is available.

Any thoughts, insights, gotchas I should be aware of?

Thanks!

webdoctor

4:31 pm on Feb 19, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



IMHO it depends on whether you need to validate at each step of the form, or at the end.

Merging arrays is fine if you're only validating at the end, but most of my multi-page forms validate at each step, so that the end-user can't proceed off page one until the values are appropriate.

How are you planning to handle validation?

millyre

8:47 am on Feb 20, 2006 (gmt 0)

10+ Year Member



I'm thinking of using javascript for validation, and including separate validation code for each form page.

For server side validation, I've made a first attempt to write a simple controller for a multi-page form including validation code:

//** if $_POST, validate page and continue, else display page 1 **
if ($_POST) {
$current_page = $_POST['_current_page_'];
$ary_errors = validate($current_page, $_POST);

//** if any errors, display same page with errors **
if ($ary_errors) {
display_page($current_page, $_POST, $ary_errors);
//** else merge data and go back/next/submit **
} else {

//** get current state from hidden field, merge **
$ary_state = unserialize(gzuncompress(base64_decode($_POST['_state_'])));
$ary_state = array_merge($ary_state, $_POST);

//** update state field, might want to compress the data?
$tmp = base64_encode(gzcompress(serialize($ary_state)));
$ary_state['_state_'] = $tmp

//** submit **
if ($_POST['_submit_']) {
submit_form();
//thank you
//** display page according to button pressed **
} elseif ($_POST['_goto_page_1']) {
display_page(1, $ary_state, NULL);
} elseif ($_POST['_goto_page_2']) {
display_page(2, $ary_state, NULL);
} elseif ($_POST['_goto_page_3']) {
display_page(3, $ary_state, NULL);
/** or else first page **
} else {
display_page(1, NULL, NULL);
}
}
/** or else display first page **
} else {
display_page(1, NULL, NULL);
}

function display_page($current_page, $ary_state, $ary_errors) {
include('form_page_' . $current_page . '.tpl');
}

function validate($current_page, $post_values) {
...
}

form_page_1.tpl:
<form>
<input type="hidden" name="_current_page_" value="2" />
<input type="hidden" name="_state_" value="<?=$ary_state['_state_']?>" />
<div class="error"><?=$ary_errors['sometextfield']?></div>
<input type="text" name="sometextfield"
value="<?=$ary_state['sometextfield']?>" />
<input type="submit" name="_goto_page_1_ value="Back" />
<input type="submit" name="_goto_page_2_" value="Next" />
</form>