Javascript form validation

   —   

In some unique cases, you may want to validate certain form fields using javascript rather than postback. Let’s find out how to do that!

Here’s the scenario: You’ve got a form that accepts an email address. Then you decide to allow visitors to upload a file in the form as well. So, you add a field that uses the Direct Upload form control, and everything’s working great.

Now, you notice users are uploading files without filling in the email field, so you mark the email field as required. When you test the form out on the live site by uploading a file and not entering an email address, you are instructed to fill in the email field, but the file you uploaded disappears!

This is a standard issue with .NET development: uploader controls lose their data upon postback. You don’t want users to have to re-upload their file every time a field fails validation, so you decide to validate the email field using javascript and avoid the postback altogether. So, how do you do this in Kentico?

 

1. Modify the field

In your form, create or modify the Email field with Data Type “Text” and Form Control “Text box”. Under the CSS styles category in the Control CSS class property, enter the class name “js-validation-email.” We will refer to this class in our javascript file.

Also mark the field as not required since we’ll be validating the input via javascript instead of using Kentico’s built-in validation.

 

2. Load the script

We now need to load our custom javascript. Copy the code below and include the javascript on your page by linking to a file created in the Javascript application, directly within a Javascript web part, or in the page template’s head section. An external javascript file created via the Javascript application is preferable as it is easily manageable.

var email_regex = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i; window.onload = function(){document.getElementById("form").onsubmit = validateForm;} function validateForm(e){ var error_message = validateFields(); if(error_message !== ""){ e.preventDefault(); alert(error_message); } } //Add your field validation to this function function validateFields() { var result = ""; result += validateEmails(); result += validateIntegerMin(); result += validateIntegerMax(); return result; } //Gets all fields with js-validation-min-XXX and validates that the input value is >= XX function validateIntegerMin() { var val, min, matches, str = ""; var inputs = document.getElementsByClassNameWildcard("js-validation-min-"); for(var i=0; i<inputs.length; i++){ matches = inputs[i].className.match(/(\s|^)(js-validation-min-)(\d+)/); if(matches){ val = Number(inputs[i].value); min = Number(matches[3]); if(val < min) str = addError(str, "The value must be at least "+min, inputs[i]); } } return str; } //Gets all fields with js-validation-max-XXX and validates that the input value is <= XX function validateIntegerMax() { var val, max, matches, str = ""; var inputs = document.getElementsByClassNameWildcard("js-validation-max-"); for(var i=0; i<inputs.length; i++){ matches = inputs[i].className.match(/(\s|^)(js-validation-max-)(\d+)/); if(matches){ val = Number(inputs[i].value); max = Number(matches[3]); if(val > max) str = addError(str, "The value cannot be greater than "+max, inputs[i]); } } return str; } //Gets all fields with js-validation-email class and performs regex validation function validateEmails() { var val, str = ""; var inputs = document.getElementsByClassName("js-validation-email"); for(var i=0; i<inputs.length; i++){ val = inputs[i].value; if(val === "") str = addError(str, "You must provide an email address.", inputs[i]); else if(!val.match(email_regex)) str = addError(str, "Address '"+val+"' is not valid!", inputs[i]); } return str; } function addError(str, msg, element) { str += "\u2022"; if(element !== undefined && element !== null){ var label = findLableForControl(element); if(label !== undefined && label !== null) { str += label.innerHTML; if(!str.endsWith(":")) str += ":"; } } str += " "+msg+"\n"; //Change '\n' to '<br/>' if displaying error message in HTML return str; } function findLableForControl(el) { var idVal = el.id; var labels = document.getElementsByTagName('label'); for( var i = 0; i < labels.length; i++ ) { if (labels[i].htmlFor == idVal) return labels[i]; } } //Custom function used to select elements with classnames using regex document['getElementsByClassNameWildcard'] = function(str){ var arrElements = []; function findRecursively(aNode) { if (!aNode) return; if (aNode.className !== undefined && aNode.className.indexOf(str) !== -1) arrElements.push(aNode); for (var idx in aNode.childNodes) findRecursively(aNode.childNodes[idx]); }; findRecursively(document); return arrElements; };

You can see that the validateFields() function has 3 built-in validation methods that use predefined classnames:

  • js-validation-email
  • js-validation-min-xx
  • js-validation-max-xx

You can add as many custom validations here as you’d like, for any number of fields. The validateEmails() function will select all inputs with the class “js-validation-email” and use a predefined regex to validate the value.

The validateIntegerMin()/validateIntegerMax() functions are for validating integer fields. You can enter any valid integer in the class name, for example “js-validation-min-100.” This will set the minimum value of that field to 100. A class name of “js-validation-max-100” will work similarly, setting the maximum value to 100. You can even use these classes together to set a minimum and maximum value: “js-validation-min-100 js-validation-max-200.”

 

3. Test it out!

With the custom script now loading on the page, upload a file then attempt to submit the form without an email address. The page will not postback, and you will receive an error stating that the email field is required. If you enter an invalid email, you will receive another error message, but the file will remain uploaded during the whole process. Once the email is valid, the form will submit as usual.

This is only one example of why you would want to use this functionality, and only contains validation for two types of data. This sample code can be expanded upon to include validation for any number of fields. Another example of usage for the functionality would be to validate fields against the results of an AJAX call, submitting this information to a third-party javascript application, custom site analytics, and many others.

 

Special cases

In many cases, you will need to pay close attention to where the Control CSS class from Step #1 appears in the control’s generated HTML. For example, when using a Calendar form control, the CSS class is applied to a <span> rather than the <input> box.

To validate this field from javascript, you would need to get the input by selecting the children of the <span> element.

Share this article on   LinkedIn