www.RickBull.com > tutorials > JavaScript > Validating HTML Forms with JavaScript

Validating HTML Forms with JavaScript

Introduction

This page will show you some ways of checking that the user has entered valid information into a form. The basic principle is that in the onsubmit event-handler of a form you return either true or false to let the form submit or not (respectively). So if the user has not entered valid data you return false to stop the form submitting (usually accompanied by an alert box telling the user of their mistake).

Generally you will want to make up a function that will check the form's data, and only return true if all is OK. So it could look something like this:

function validateForm(formElement) {
  //Check formElement's data here, and return false on error...

  //Function will only get this far if there is no error
  return true;
}

Obviously that is missing all the actual validation code (which we will get to in a minute), but here is an example of how you would call it in your HTML:

<form action="some_page.php" onsubmit="return validateForm(this);">

So when the user submits the form, it will go through the validateForm function and check for errors. One common mistake that a lot of people make is to have the validation function occur when the user clicks the submit button like so:

<input type="submit" onclick="return validateForm(this.form);" />

This is incorrect as that method will only validate the form when the user clicks the submit button. What happens when the user presses enter in a text-box? The validation routine will not be called, and your code will be wasted! So just make sure you use the onsubmit event-handler of the form rather than the onclick handler of the submit button.


Textual data

Checking lengths

A common thing to validate is the length of text, e.g. to make sure have 5 or more characters for a password. This is fairly simple, as every String object has the length attribute, which tells you (unsurprisingly) its length. So let us assume that we have the following form and text-box:

<form action="some_page.php" onsubmit="return validateForm(this);"><p>
  <input name="pass" type="password" />
</p></form>

In out validation routine we could check the length something like this:

if (formElement.pass.length < 5) {
  alert('Please enter a password that is at least 5 characters long');
  return false;
}

So in this example formElement is the form that is calling this function (remember we passed it into the function with this line of code: return validateForm(this);). Then we refer to the password text-box (pass) and then its length. If it is less than 5 then we tell the user and return false which stops the form from submitting.

You could also check that the length of the text is not too big:

if (formElement.pass.length > 10) {
  alert('Please enter a password that is less than 10 characters long');
  return false;
}

Or we could even check that it is between to values:

if (formElement.pass.length < 5 ||
    formElement.pass.length > 10) {
  alert('Please enter a password that is between 5 and 10 characters long');
  return false;
}

The double bar (||) means logical or; So if the password is less than 5, or greater than 10 then tell the user.

If you just want to make sure that the user has entered a value you could use a simpler method, as shown below:

if (formElement.pass.value == '')

When you are checking for equality you have to use the double equals sign (==). So the above statement says if the pass field is equal to an empty string (''), then do the following….

Checking for valid e-mail addresses

Sometimes you will want to make sure that the user has entered a valid e-mail address. Well there is some code that you can use to check this, which is listed below:

function validEmail(email) {
  var emailRE = new RegExp(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/);
  return emailRE.test(email);
}

Then you can test if a text box has a valid e-mail address:

if (validEmail(formElement.email) == false) {
  //Tell user to enter a valid e-mail address...
}

Thanks go to Tom Howells for this code.


Checking select lists

Single select lists

With lists we may want to make sure the user has not selected an unwanted value. The way we can find the value of the selected item is:

form.select.options[form.select.selectedIndex].value

So if we had a form like this:

<form action="some_page.php" onsubmit="return validateForm(this);"><p>
  <select name="country">
    <option value="none">Please choose your country</option>
    <option value="United Kingdom">United Kingdom</option>
    <option value="Russia">Russia</option>
    <option value=""India">India</option>
    <option value=""Africa">Africa</option>
  </select>
</p></form>

…and we wanted to make sure the value was not none, we could do something like this:

if (formElement.country.options[formElement.country.selectedIndex].value == 'none') {
  alert('Please choose a country');
  return false;
}

We could also do something like this if we omitted a value for the first option (<option>Please choose your country</option>) like so:

if (formElement.country.options[formElement.country.selectedIndex].value.length == 0) {
  alert('Please choose a country');
  return false;
}

Multiple select lists

Select boxes do not always limit the user to selecting only one option. With the multiple attribute present, the user may select several items. So if we wanted to check the following list to make sure it has at least one selected option…

<form action="some_page.php" multiple="multiple"
 size="5" onsubmit="return validateForm(this);"><p>
  Tell us what we need more of on our site:
  <select name="need_content">
    <option value="nothing">Nothing, your site is perfect!</option>
    <option value="news">News</option>
    <option value="downloads">Downloads</option>
    <option value="pictures">Pictures</option>
    <option value="games">Games</option>
  </select>
</p></form>

…we could check for it like this:

if (formElement.country.options[formElement.country.selectedIndex].value == -1) {
  alert('Please select at least one thing we need more of on our site.');
  return false;
}

Check boxes and radio buttons

You can find out if check-boxes and radio buttons are selected (or checked) by using the checked property:

form.checkbox.checked

Which will return true if it is selected, and false if not. For more details on making sure at least one checkbox or radio button is selected, please see the example form/script below.


Using confirm

Before I finish with this tutorial and show and example form/script, I would just like to show you about the confirm prompt. When you use confirm it presents the user with a message box, that has OK and Cancel buttons. When the user chooses OK it returns true, and false for Cancel. So you can, for example, return a value based on the user's choice:

<form action="some_page.php"
 onreset="return confirm('Are you sure you want to reset this form?');"
 onsubmit="return confirm('Are you sure you want to continue?');"><p>
  <input value="Change this default text, then hit reset or submit." />
  <input type="submit" />
  <input type="reset" />
</p></form>

You may have noticed in that example there there is also an onreset event-handler, which is called when the user resets the form. Try out the above example for an idea of how confirm works.


Putting it all together

So you have learnt how to validate various form elements, but you have not seen a finished example. Well here is an example, including a function that will focus and select an invalid element (focusElement) that will help cut down the amount of code you need (not to mention easier to change in the future):

The JavaScript

<script defer="defer" type="text/javascript"><!--
  /*Start of form validation:*/
  function validateForm(formElement) {
    //Check user name is at least 2 characters long
    if (formElement.user_name.value.length < 2)
      return focusElement(formElement.user_name,
       'Please enter a name that is at least 2 characters long.');
    //Check password is at least 5 characters long
    if (formElement.pass.value.length < 5)
      return focusElement(formElement.pass,
       'Please enter a password that is at least 5 characters long.');
    //Check for valid e-mail address
    if (validEmail(formElement.email.value) == false)
      return focusElement(formElement.email,
       'Please enter a valid e-mail address.');
    //Make sure a location is selected
    if (formElement.location.selectedIndex == 0)
      return focusElement(formElement.location,
       'Please select your country.');
    //Make sure a location is selected
    if (countSelectedOptions(formElement.interests) < 2)
      return focusElement(formElement.interests,
       'Please select at least 2 of your interests.');
    //Make sure we have an action
    if (countSelected(formElement, 'radio', 'action') == 0) {
      alert('Please choose the action for this submission.');
      return false;
    }
    //Make sure there is at least one of the how did you find out about us check boxes selected
    if (countSelected(formElement, 'checkbox', 'how') == 0) {
      alert('Please select how you found out about us.');
      return false;
    }

    //If all is OK, return true and let the form submit
    return true;
  }
  /*End of form validation.*/

  /*Below are various functions that can be
   re-used in your own validation scripts:*/
  function focusElement(element, errorMessage) {
    //Tell the user an error has been made
    alert((errorMessage.length > 0) ? errorMessage :
      'You did not enter valid data; Please try again');
    //Select the text in the input box, and focus it (if possible)
    if (element.select) element.select();
    if (element.focus) element.focus();
  
    return false;
  }
  function countSelected(formElement, inputType, inputName) {
    //If there is no input type, make it checkbox
    if (inputType == null) inputType = 'checkbox';
    var returnValue = 0;
    //Loop for all elements in this form
    for (var loopCounter = 0; loopCounter < formElement.length; loopCounter++) {
      //If this element is the wanted type
      var element = formElement.elements[loopCounter];
      if (element.type == inputType && element.checked == true) {
        //If we have the correct control name, increment the count
        if (inputName.length > 0)
          if (element.name == inputName)
            returnValue++;
        else
          returnValue++
      }
    }
    //Return the count
    return returnValue;
  }
  function countSelectedOptions(selectElement) {
    var returnValue = 0;
    //Loop for all options
    for (var loopCounter = 0; loopCounter < selectElement.options.length; loopCounter++)
      if (selectElement.options[loopCounter].selected == true)
        returnValue++;
    return returnValue;
  }
  function validEmail(email) {
    var emailRE = new RegExp(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/);
    return emailRE.test(email);
  }
  /*End of functions.*/
//--></script>

Just in case you are wondering, the defer attribute simply tells the browser not to bother reading through the script until the page has finished loading. It is not necessary, but if the enclosed script does not have any output (e.g. no document.write()) you may as well use it, so that it can help some browsers load the page a little quicker.

The HTML

And here is the HTML form that works in conjunction with the above script. Just place the script in the same document as this form and it should all work fine.

<form action="some_page.php" onsubmit="return validateForm(this);"
 onreset="return confirm('Are you sure that you want to reset this form?');">
  <fieldset><legend>Questions:</legend><table
   summary="This table holds a questionnaire about our site.">
    <caption>Questionnaire</caption>
    <colgroup><col /><col /></colgroup>
    <tr>
      <th><label for="user_name">Name</label></th>
       <td><input id="user_name" name="user_name" type="text" /></td>
    </tr>
    <tr>
      <th><label for="pass">Password</label></th>
       <td><input id="pass" name="pass" type="password" /></td>
    </tr>
    <tr>
      <th><label for="email"><acronym title="Electronic">E</acronym>-mail</label></th>
       <td><input id="email" name="email" type="text" /></td>
    </tr>
    <tr>
      <th><label for="location">Location</label></th>
       <td><select id="location" name="location">
         <option>Please select your country</option>
         <option value="Europe">Europe</option>
         <option value="Africa">Africa</option>
         <option value="Asia">Asia</option>
         <option value="Americas">Americas</option>
         <option value="Other">Other</option>
       </select></td>
    </tr>
    <tr>
      <th><label for="interests">Your interests</label></th>
       <td><select id="interests" multiple="multiple" name="interests" size="5">
         <option value="music">Music</option>
         <option value="tech">technology</option>
         <option value="sci">Science</option>
         <option value="sport">Sport</option>
       </select></td>
    </tr>
    <tr>
      <th>Action</th>
       <td>
         <input id="action_email" name="action" type="radio" value="email" />
          <label for="action_email"><acronym>E</acronym>-mail to me</label>
         <input id="action_board" name="action" type="radio" value="message_board" />
          <label for="action_board">Add to message board</label><br />
       </td>
    </tr>
    <tr>
      <th>How did you hear about this site?</th>
       <td>
         <input id="how_friend" name="how" type="checkbox" value="friend" />
          <label for="how_friend">from a friend</label><br />
         <input id="how_site" name="how" type="checkbox" value="site" />
          <label for="how_site">another site</label><br />
         <input id="how_search" name="how" type="checkbox" value="search engine" />
          <label for="how_search">search engine</label><br />
         <input id="how_other" name="how" type="checkbox" value="other" />
          <label for="how_other">other</label>
       </td>
    </tr>
  </table></fieldset>
  <p><input type="submit" /><input type="reset" /></p>
</form>

Validating on other events

You do not need to do all of your validation on the form's onsubmit event-handler; Most HTML elements have some event, some of which maybe more appropriate for what you are doing. For example onblur is called when the element had the focus, and the user changed to another control (which is usually an indication that they have finished with the current input field). So we could do something like this for example:

<input name="pass" type="password" onblur="if (this.value.length < 5) { alert('Please enter a value that is at least 5 characters long.'); this.focus(); }"

Another useful event is onchange. This event occurs when an input's value is changed and has lost focus (one exception to this rule is for the select box, whose event occurs as soon as you click one of its options):

<select onchange="if (this.options[this.selectedIndex].value == '') alert('Please select a valid option.');">
  <option>Select from the list below</option>
  <option value="value1">Option 1</option>
  <option value="value2">Option 2</option>
</select>

The onclick event can also be handy for elements such as check boxes and radio-buttons, which is called when their value changes.


Notes


All tutorials and content written by Rick Bull unless otherwise stated
Page's last update: Friday, 15th January 2010; 12:54:44 UTC +0000
Thanks to Tom Howells for the ideas for the sections Validating on other events (as well as spelling and grammatical corrections).
Top of the page