![]() |
|||||||||||||
|
This article was written for Evolt.org. Forms are used frequently in dynamic web applications. As a consequence, almost all web programmers have to deal with form data validation at some point in their careers. The technique described in this article will help you help the user submit correct information. So, what's the technique? Building smart forms... well, smart validation, actually. You are validating your forms on the server side, aren't you? You don't want to validate only on the client side. I can't tell you how many web sites I've visited that don't handle input errors correctly. They either have forms that simply refresh with a generic "Your input has errors" message or they only report the first input error the validation script encounters (you'll have to turn off client-side scripting to view this gem). An example on PowerASP.com has the beginnings of TheRightIdea™ and is worth a once-over. However, they miss the logical way of form validation and processing. The article details how to process forms and report one or more input errors using a form handler script and a redirect back to the form if there are input errors. Other than the fact that this method isn't the most logical way of doing things, there is also a loss of all of the users input unless they are also passed along in the querystring. Wasn't this supposed to be easy? Writing smart forms can be easy if you want it to be. I'm going to use ASP in the actual examples, but the general concept can be applied using any language — except ColdFusion; you just can't do ANYTHING good with that (direct flames to flames@mattwarden.com). The Basic ConceptThere are a number of benefits gained by displaying and handling a form in the same file. First, we have all of the code related to that form in a single location (with the exception of code in include files). Second, we have available to our script every submitted form variable. The general flow of our form processing is as follows:
As you can see, we are validating the form before redirecting to any other page. In other words, the form is submitting to itself. Within this script, there is logic which determines whether it should display the form or process submitted form information. We are only moving from our script if the submitted form passes our validation. If the information does not pass validation, we re-display the form. We also pre-fill the form fields with the information already submitted and mark the fields that didn't pass our validation. This makes it easier for the user to supply the correct information. So, let's say Joe User fills out the following form:
We don't like some of his input and our validation methods rejected it. Joe didn't even fill in his last name. He didn't even try with his email address. And that zip code is not the zip code for Evoltageddon, NH. How do we present these issues to Joe User? Should we just tell him he screwed up and have him doing the work trying to figure out what is wrong (even though we've already figured out what's wrong)? No. We indicate to him that there is a problem with his submission with some generic text and highlight the fields that need to be corrected. The important part here is that both his correct and incorrect data is preseved so he doesn't have to re-type the correct information and he can also see what was wrong with his other information. So, we show Joe something like this:
You could take it a step further and display what was wrong with each field, but that is overkill for most situations. In this example, the only field that could warrant an explanation is the zip code field. However, the marked fields should do fine and there is only a very small chance that Joe will get confused. What does this mean? Well, when you're building forms (and form handlers) you should:
The Basic CodeHow can we determine whether to display or process the form? Some people like to pick a form field and test it for a value. For instance: This method isn't the best way to do things. If I fill in every field but the first name field, the form is simply re-displayed, with no error notification (because the code doesn't know there's an error). Another method is to pick the name of the submit button as the field to test:
The above code simply checks if request.form("submitButton") has a value. If it doesn't, it calls
a subroutine called displayForm(). This subroutine simply writes the HTML for the form. If it
does have a value, it calls processForm(), a subroutine that validates the form input. You could
also skip the subroutines (but, it's so much cleaner looking, eh?) and slop all the code for each
condition within the Still, I don't like this method much. If the value attribute of the submit button tag is omitted, isEmpty(trim(request.form("submitButton"))) will always be true. This is an easy thing to catch, but why bother when there are easier ways of doing things?
The method I prefer uses the server variable REQUEST_METHOD. Most likely, when Joe User first
visits your form page, his browser will use the GET method. When the form is submitted, the browser
will use the POST method (you are using What is an easy way to make a form self-submitting? Simple. Another server variable available is SCRIPT_NAME. This holds the root-relative path as well as the filename of the current script. How can I pre-fill fields with submitted data after an input error has been found? Also fairly simple. Because the form is self-submitting, you have all the submitted form information at your disposal. Note that if you already have these form values stored in variables (which you should if you've already run the submitted values through validation), you should use those values rather than accessing them from the request object. More It gets a little complicated if the form's purpose is to edit saved data in the database. The form will already have data in it before the user inputs anything. So, if they change something and there's an error with what they've changed, do you show the data from the database and let them re-edit that, or do you display what they've just entered? Truthfully, it's a mix. Here, we're going to give importance to the form data just submitted:
The function So, how do I do this validation? Well, it obviously depends on the information you're validating. However, in my experience, there are a few things that makes everything go a lot easier. We need to know two things. First, we need to know if all the data validated. We also need to know which bits of data validated and which did not.
Here we have four variables. The first,
Here,
Also note that After I've validated, how do I mark problem fields?
The easiest way to do this is to use the same subroutine you used to display
the form in the first place. In this example, it was called displayForm().
Now we have to add the highlighting functionality so that the user knows
which fields had errors. Ok, at this point (assuming the form has already
been submitted), we know whether the first name, last name, and email address
are valid. The variables Now, we run into a problem when the form is first viewed (before submission). All of those variables are going to be false. So, up where we're doing validation, we need to account for this case: And I'm sure you can think up some nice ways of getting around checking the REQUEST_METHOD twice in the same script ;-) Cool?
A Caveat
Sending a response.redirect (or equivalent in your language of choice) generates
a HTTP response code of 302 (the requested file has been found but it is in a
different location). Rather than it executing the redirection by requesting
the new location, in very old browsers an "Object Moved" page might be
displayed. This is obviously not something we want. In ASP, there is a method of
the
|
|||||||||||||
| top | |||||||||||||
| Valid XHTML 1.0 Strict Valid CSS |
|||||||||||||
| Last Updated on May 02 2009 01:56:25. | dev@mattwarden.com | ||||||||||||