Skip to main content

Form Validation Without jQuery

Tags

JavaScript

Over the last month I have been tearing a lot of jQuery out of a pretty large JavaScript application and noticed that to completely removed jQuery from my application I am going to need to come up with a clever way to reproduce jQuery Validate. This decision made me pause for a moment because jQuery Validate is a pretty nice library for validating HTML forms and trying to reproduce this functionality seemed like a waste of time.  As I thought about it more I concluded that if I could write something to replace jQuery Validate that was a lot smaller than 22 KB in size (the size of jQuery Validate minified) then it would be worth the work it took to remove the library, not to mention jQuery.   What I came up with as a solution was to create a JavaScript module out of this form validate routine, that way I could keep my code small and easy to use and if needed plug it into any future projects.  

The baseline functionality of the module I created is pretty straight forward,  define the form elements I am validating on, define the validation rules for those elements, and then define an error message for those elements.  After all of that is defined the only thing left to do is to bind the form elements to a validation function so that the module can parse the element, decide which rule is needed to apply, and then either ignore the field because the input is valid or set the error message and halt the submission of the form.  The current functionality of this module is only setup for input and checkbox fields at the moment, but the current logic could be extended for other fields like select and radio buttons also.

Here is the JavaScript module.  This portion of the code is designed to be lightweight and easy to read.  For example, when you are using jQuery Validate you are loading all the validation rules for every HTML form element out there and then in JavaScript just defining the ones you want to use.  This module is designed to only use a couple of needed input fields that your project requires making the code that runs this routine small and easy to understand.

/**
 * @file
 * A JavaScript module to validate forms
 */
 
 
module.exports = {
 
  forms: [],
  form_elements: [
    'username',
    'email',
    'password'
  ],
  form_element_rules: [
    {'required': true, 'minLength': 5},
    {'required': true, 'email': true},
    {'required': true, 'minLength': 5}
  ],
  messages: [
    'A 5 character username must be provided',
    'Please provide a valid email',
    'A 6 character password must be provided'
  ],
 
  /**
   * Peforms Validation
   */
  perform_form_validation: function(e) {
 
    e.preventDefault();
 
    var submission_flag = true;
    for (var i = 0; i < module.exports.form_elements.length; i++) {
      var form_element = document.getElementById(module.exports.form_elements[i]);
      if (form_element) {
        var rules = module.exports.form_element_rules[i],
        type = form_element.type;
 
        // Required validation option
        if (rules.required) {
          // nothing should be less than four character
          if (type == 'checkbox' && !form_element.checked) {
            // display error about terms and conditions
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], module.exports.messages[i]);
            submission_flag = false;
          } 
 
          if (type == 'checkbox' && form_element.checked ) {
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], '');
          }
 
          if (type != 'checkbox' && form_element.value.length < 1) {
            // display error about being required
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], module.exports.messages[i]);
            submission_flag = false;
          } 
 
          if (type != 'checkbox' && form_element.value.length > 0) {
             module.exports.set_form_element_label_with_message(module.exports.form_elements[i], '');
          }
 
        }
 
        // Minimum length validation option
        if (rules.minLength) {
 
          if (form_element.value.length < (rules.minLength + 1)) {
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], module.exports.messages[i]);
            submission_flag = false;
          }
 
          if (form_element.value.length >= (rules.minLength + 1)) {
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], '');
          }
        }
 
        // Email validation option
        if (rules.email) {
          var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
          if (!re.test(form_element.value)) {
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], module.exports.messages[i]);
            submission_flag = false;
          }
 
          if (re.test(form_element.value)) {
            module.exports.set_form_element_label_with_message(module.exports.form_elements[i], '');
          }
        }
      }
    }
 
    if (submission_flag) {
      module.exports.forms[0].submit();
    }
  },
  /**
   * Sets the error label
   */
  set_form_element_label_with_message: function(element, message) {
    var requesting_element = document.getElementById(element + '-error');
    requesting_element.innerHTML = message;
  }
};

Here is the JavaScript to include in your project to require the module and attach the functionality to a form that carries the class of .validation.

<script type="text/javascript">
var validation = require('./modules/validation/validation.js');
validation.forms = document.querySelectorAll('.validation');
 
 
for (var i = 0; i &#60; validation.forms.length; i++) {
  validation.forms[i].addEventListener('submit', validation.perform_form_validation, false);
}
</script>

Here is an example of an HTML log in form.  As you can see there are two input fields and under the input fields there are two error labels that are blank by default.  These labels carry the id prefix of their input field they are attached to and then the -error suffix is just added on so that the module knows which error message to set to which input field.

<form action="/login" method="post" class="validation" accept-charset="UTF-8">
   <div class="inside">
     <div class="form_item form_type_textfield form_item_name">
       <label for="edit_name">Username <span class="form_required" title="This field is required.">*</span></label>
       <input type="text" id="login_username" name="login_username" value="" size="60" maxlength="60" class="form_text required" autofocus>
       <div class="description">Enter your username.</div>
       <label id="login_username-error" class="error" for="login_username"></label>
     </div>
     <div class="form_item form_type_password form_item_pass">
       <label for="edit_pass">Password <span class="form_required" title="This field is required.">*</span></label>
       <input type="password" id="password" name="password" size="60" maxlength="128" class="form_text required">
       <div class="description">Enter your password.</div>
       <label id="password-error" class="error" for="password"></label>
     </div>
     <div class="form_actions form_wrapper" id="edit_actions">
       <input type="submit" id="edit_submit" value="Log In" class="form_submit">
     </div>
   </div>
</form>

Member for

3 years 9 months
Matt Eaton

Long time mobile team lead with a love for network engineering, security, IoT, oss, writing, wireless, and mobile.  Avid runner and determined health nut living in the greater Chicagoland area.

Comments

Daniel

Thu, 03/10/2016 - 03:13 PM

I'm faced by the same issue and think about using validate.js. It's independent of any libraries like jQuery and quite lightweight (2kb).

Validate.js looks pretty easy to implement, and you are right, the minified version is small enough where it makes the library very appealing when trying to make the decisions about whether or not to add in an external library.  Thank you very much for bringing this library up, Daniel.