Thursday, April 27, 2006

SnTT: Good Looking and Useable Form Validation

Ah...Form validation. A subject that could probably fill several tomes and has been source of debate since the web browser was first introduced. There are probably as many ways to implement validation on your web forms as there are opinions about the best way to do it. Even though there is a ton of information out there about the hows and whys of form validation, I still see many sub-par implementations of the concept in Domino-based web sites. This certainly has nothing to do with the technology itself. I think most of us know by now that you can do just about anything in Domino...even if it calls for righteous hacks. :-) So...what's the reason for poor validation techniques in Domino. Typically I've found that it's just that developers aren't aware of some simple, yet powerful ways to use web technologies in their apps. The purpose of this entry is to introduce you to a really easy technique that you can implement right away to have nice clean, useable validation in your Domino forms.

For our purposes today, I'm going to use client-side validation. That is, we'll use JavaScript to check the fields before the form is ever submitted to the server. This is fast and efficient, since we let the client do the work. Unfortunately, this can be handled very poorly. The most common implementation of client-side form validation I see is the use of the JavaScript alert function, which pops up a message to the user telling them that they forgot to fill in a certain field. This might be OK for only one or two fields, but beyond that it is bad news from a usability perspective. What typically happens is that the user fills out the field referenced in the alert box and then clicks the submit button again. If there is another field that fails validation, then an error message for that field pops up. this several times and bye bye user.

Aside: Always remember you can't just rely on client-side validation to do your work. Your user might have JavaScript disabled or a tricky hacker might find an easy way to exploit a hole in your app. Client-side validation is great for quick, immediate feedback to the user without requiring a trip to the server, but you have to do your true validation on the server-side.

A slightly better way is to provide a list of all fields that failed in a single alert call. At least this time the user knows everything that went wrong. The problem is the limited memory retention that we have. Once the user clicks the OK button to dismiss the dialog box, that's it...the validation message is gone. If there are several fields listed, the user either has to remember all the fields that need to be fixed or they have to jot them down. Again, not the best solution when you are striving for a useable app.

You can get really fancy with server-side validation, since you can write in lots of error information when you present the form back to the user. But in our case, how can we provide useful error information that doesn't interfere with the rest of the interface and still be quick and lightweight? Here's a picture of what I'm striving for. This example is from Amazon. Although their validation is done server-side, I want to mimic this kind of idea for my Domino forms.


Here's the cool trick and secret to doing this...I create a hidden div which is used to display my validation messages. If validation fails, this div is revealed to the user. If you place this at the top of your form, the user sees the feedback immediately and can continue filling in the form while still referring back to the error messages. Of course, since this is all just HTML and CSS, your div can be positioned anywhere it makes sense in the context of your form. This is really flexible and easy!

The code to handle all of this is quite easy. First, check out the sample to see how this works...then come back.

OK...that's pretty cool, eh? Here's the code for the div that holds the error messages.

This div is empty and has a class I called "hideMe". For simplicity, my CSS definition for the classes that will show or hide this information looks like:

In practice, these classes might have more to them, but it's not necessary right now.

The "ErrorMsg" div resides at the top of the form. When the user tries to submit the form, the validation code is called. You can use whatever validation code you currently have (Jake has done some great stuff with this). In order to get this to work with your current validation routine, you'll just have to do a couple of extra things:

1. Construct your error message using HTML.
2. Write this message to the "ErrorMsg" div.
3. Show the "ErrorMsg" div by changing it's class to "showMe".

For this example, I took a very streamlined part of Jake's code to demonstrate. Here's the whole scenario step by step.

1. User opens the page and clicks the 'Continue' button. This invokes a call to the 'canYouDigIt' function.

2. 'canYouDigIt' builds an array to hold the required fields and the text that you want displayed in the error message.

3. It then calls the 'validateRequiredFields' function and submits the form if all is OK. If validation fails, it builds the HTML code that will be displayed to the user and then places that code in the "ErrorMsg" div using the innerHTML property. When that is done, it calls 'showIt' function to change the "ErrorMsg" div class to "showMe".

Note: empty_fields is a global variable that is declared in the JS Header.

In the event that validation fails, the HTML that you construct can be as simple or complex as you want. In this case, I built a fieldset and placed a table within that fieldset.

That's all there is to it. The cool thing about this solution is that it is pretty easy to plug in anywhere and requires a fairly small amount of code. Of course, there's a lot that can be done to improve it. Let's look at one other usability enhancement. I find that users really like it when they not only get a message of what needs to be fixed, but when they get a visual indicator on the fields themselves. This can be accomplished with the addition of just a couple more lines of code. In your validation code, when you find a field that fails validation, set the class of that field to "formerror". Then, in your CSS, define the properties you want for the "formerror" class.

Here's what I used:

With this little enhancement, the background color and border color of the field is changed and a small image appears. If this doesn't get their attention, then all is lost! ;-)

You can see how all this fits together by viewing the source of my sample page, but for completeness, here is the remainder of the code that does all the work. The code that is important for this example is the line where the class of the field is set to nothing (to reset possible past errors) and when it is set to "formerror" in the event that the field is blank.

If you got this far, congratulations...boy can I ramble on! :-) Anyway, I hope you find this a useful and user-friendly form validation technique. If you'd be interested in having this in a sample database, please leave a comment or ping me and I'll put one together. Cheers!

Technorati tags:


Anonymous said...

I love this script and am adapting it to a project I'm working on. I've found it doesn't work for fields of type "dialog list". It always returns them as being empty. Before I dig in, I thought you might know offhand the modification I need to make to get it to work with that type of field. If so, please post the answer here for everyone's benefit.


Chris Blatnick said...


Yes...the script here is a pretty pared down version just to demonstrate the concept. I have been using (with great success), Jake Howlett's awesome script with modifications to support this kind of error handling. Here's my modified code. If you have any questions, feel free to shoot me a Cheers!

Rock (Lotus Geek) said...

Late to the party (sorry), but wanted to say a nice post! BTW, I wanted to let you know that I have added you to the Lotus Geek Honor Roll for flying the LotusGeek button :)

Good job!


Chris Blatnick said...

Thanks Rocky! I never planned on being a Lotus geek, but it just kind of happened...and I'm certainly glad it did! :-)

Gana said...

This is the kind of validation one can easily accomplish with Java & ASP.NET (even simpler!)

Somehow Domino is missing them.