views:

68

answers:

2

I have a three step form where each step posts to it's own action; the action redirects to the next step. The data is stored in the session scope. I have a filter that prevents a user from accessing the form handlers through anything other than a post request.

There's nothing to stop someone from manually typing in the address of a step, however. To deal with this problem I set a currentStep variable in the session.

<!--- Some data is processed here --->
<cfset session.currentStep = "stepTwo">

And in step two I would check for a structkey:

<cfif NOT session.currentStep = "stepTwo">
<!--- redirect to #session.currentStep# --->

This approach works well, but it has a major draw-back: A user can not press the back button in the browser window, or edit any data he or she has already entered.

What are some the best practices to implementing a multi-step form? Can I improve my process to incorporate back-button functionality?

A: 

You can stay using Session approach if you want.

To solve your major drawback, you can change your logic a bit.

At the last step, make sure data of all steps are found in the session. If not, redirect the user to the first unfilled step? Shouldn't be too hard.

Henry
+1  A: 

Instead of using the session variable to only allow them to access the current step, allow them to access the current or previous steps. Sort of a "how far you can go" flag.

Now, add links to the previous steps, like a breadcrumb trail.

Finally, use a lookup in the persistent store (db, session, xml, bag of holding, etc.) for the data already entered for that form. Create a blank set of form data, overwrite it with anything found in the persistent store, then overwrite it with anything from the form scope itself. Something like:

populate = structNew(); // this is the data to populate your form with on load
populate.someValue = "";
structappend(populate, dataFromStorage);
structappend(populate, form); // from things submitted from the form scope, in case validation fails
<input type="text" name="someValue" value="#variables.populate.someValue">

Now, if someone hits the same form step twice, they will see (in order of precedence) the values they submitted, but which didn't pass validation, values from the persistent data store, and then an empty form.

Ben Doom