Form Validation - The Basics

This document provides an overview about the best practices for client side form validation in JavaScript.

The recommendations made throughout this document are a collection of those given in EFnet's #javascript channel.

The Scenario

In this overview, we want the user to fill out the following form:

  1. <form action="update.aspx" method="post">
  2. <p>
  3. <label for="fname">First Name</label>
  4. <input id="fname" name="name">
  5. <label for="lname">Last Name</label>
  6. <input id="lname" name="name">
  7. <label for="email">Email</label>
  8. <input id="email" name="email">
  9. <button type="submit">Save</button>
  10. </p>
  11. </form>

As all fields are required, the script on the server returns the user to the form if one or more of the fields are empty. This is not very responsetive for the user (obviously, the post and reload of the forms page take some time and if the server is under heavy load the response time increases).

Client Side Validation

So, to improve the responsiveness of the form and to reduce the load on the server we want to add client side form validation.

Note: client side validation is not a replacement for server side validation, only a tool to improve user experience. You should always validate user input on the server.

Additions to the Form

For this overview we will validate the form data when the user submits the form. Luckily the W3C board in charge for the HTML specification added an event which we can use to execute the validation code: onsubmit. With this event the form now looks like:

  1. <form action="update.aspx" method="post" onsubmit="validateForm();">
  2. validateForm() is the validation function which is defined later

But we want to stop the submit of the form if some of the fields are not filled in. So, as events are stopped if the event handler code returns false, we change the onsubmit to:

  1. <form action="update.aspx" method="post" onsubmit="return validateForm();">

To simplify the access to the form fields in the validation function we pass the forms object to the function:

  1. <form action="update.aspx" method="post" onsubmit="return validateForm(this);">

The Validation Code

Now that we modified the form to execute the validation code when the user submits the form, we need to implement the actual validation code.

  1. function validateForm(form) {
  2. var isValid = true;
  3. // Validation code here
  4. return isValid;
  5. }
  6. The skeleton of the validation function

As noted above, we simply want to ensure that the user fills in all fields. Adding the code to check the length of the fields values results in:

  1. function validateForm(form) {
  2. var isValid = true;
  3. var msg = "The following field(s) need to be filled in:\n";
  4. // Check each field individually
  5. if(form.fname.value.length == 0) {
  6. msg += "\tFirst Name\n";
  7. isValid = false;
  8. }
  9. if(form.lname.value.length == 0) {
  10. msg += "\tLast Name\n";
  11. isValid = false;
  12. }
  13. if(form.email.value.length == 0) {
  14. msg += "\tEmail\n";
  15. isValid = false;
  16. }
  17. // Show the error message to the user
  18. if(!isValid) alert(msg);
  19. return isValid;
  20. }
  21. JavaScript Code to ensure that all form fields are not empty

Summary

The onsubmit event of the form provides a nice and easy way to validate form field data. Passing the form object to the validation function simplifies form field access. This introduction shows only the tip of the iceberg of possibilities available to do client side form validation. To name a few:

Some of these may be covered in a future article.

Supplementary Thoughts

Submit Button Names

Giving the submit button the name submit is a Bad Idea™. Reason: because of legacy browser behaviour the name of the submit button will override the methods of the form object disabling the ability to submit the form via script (even though script submitting should be a last resort only).

Accessing Elements that share the same Name

Form field elements that share a name (e.g. radio buttons) form.sharedName returns a collection.

  1. // rds is a reference to the radio buttons, e.g. var rds = form.nameSharedByRadioButtons;
  2. for(var i = 0; i < rds.length; i++)
  3. if(rds[i].checked) break;
  4. // if i equals the length of the collection, no radio button is selected
  5. if(i == rds.length) {
  6. isValid = false;
  7. alert("Please select an option");
  8. }
  9. Ensuring that a radio button is selected

Accessing Elements with special characters in Name

See PHP and SELECT naming conflicts for an indeep discussion (ignore the spec quote) of this issue.

Multiple Submit Buttons

To validate the form based on the used submit button these options are possible:

  1. Setting a flag in the onclick event of the submit button that determines the code path to be used during validation:

    1. var validateFor = 0;
    2. function validateForm(form) {
    3. if(validateFor == 0) {
    4. // validate the form for saving
    5. } else if(validateFor == 1) {
    6. // validate the form for deletion
    7. }
    8. }
    9. <form onsubmit="return validateForm(this);">
    10. ...
    11. <button type="submit" onclick="validateFor = 0;">Save</button>
    12. <button type="submit" onclick="validateFor = 1;">Delete</button>
    13. useValFunc is a global variable that determines the validation code path to be used
  2. Use a function reference in the onsubmit handler of the form and change it in the onclick event of the submit button to reference the wanted validation function:

    1. function validateSave(form) {
    2. // validate the form for saving
    3. ...
    4. }
    5. function validateDelete(form) {
    6. // validate the form for deletion
    7. ...
    8. }
    9. var validateForm = validateSave;
    10. <form onsubmit="return validateForm(this);">
    11. ...
    12. <button type="submit" onclick="validateForm = validateSave;">Save</button>
    13. <button type="submit" onclick="validateForm = validateDelete;">Delete</button>