There are plenty of articles that target how to write custom rules to the jquery.validate plugin but very few targets how this plugin internally works and that’s what we will discuss in this article
this is part of “understanding Asp.net Mvc Unobtrusive Validation” series
- How the jQuery validate plugin works internally
- Understand the Html generated by the unobtrusive validation in Asp.net MVC
- How the unobtrusive jQuery validate plugin works internally in Asp.net MVC
What we will be talking about in this article
- How to validate a form
- The validation messages and how they work
- Add custom validation rules
- What exactly happens when we call the validate method
How to validate a form ?
There are basically 2 ways to validate your form
1- Use Class names as rules
How it works
We decorate the fields that we want to validate with an html class attribute and that is what will trigger the validation
So if we want a textbox to be required we add to that input element a class value of required
<form action="/" method="post">
<input id="Name" type="text" name="Name" value="" />
<input type="submit" value="Submit" />
</form>
$(document).ready(function() {
$(‘form’).validate();
});
With this method you can define certain classes with multiple rules
Pros & cons of this approach
- only works with rules that takes no arguments
- we are using the html class attribute for something not related to its original intent which is a break for separation of concerns principle
- but still it’s very easy to setup
Using addClassRules method
Using addClassRules function gives us the ability to use compound rules as a single class
$.validator.addClassRules({
name: {
required: true,
minlength: 2,
},
zip: {
required: true,
digits: true,
minlength: 5,
maxlength: 5,
},
})
This will add 2 new class rules, name
and zip
so if we have an input element and gave it a class of zip
it will be required, the user must only insert digits and the length must be exactly 5 characters
<input class="zip" type="text" name="zipCode" />
Note: to use a custom message for a specific rule in a compound class rules requires a workaround, you have to alias the rules like required
to a new rule and in the new rule you define a default message
$.validator.addMethod(
'newrequired',
$.validator.methods.required,
'new name is required'
)
or you can use the title
html attribute and it will be the error message for the compound rule
class names validation only works on the validation rules that doesn’t accept any arguments
2- Add rules as JSON object to the validate method
by the name you should have figured out that the validation method takes a json object, we then could specify the fields that we want to validate and the validation rules for it
<form>
<input id="something" type="text" name="userEmail" />
<input id="submit" type="submit" value="submit" />
</form>
$(‘form’).validate({
rules: {
userEmail: {
email: true,
required: true
}
}
});
when you pass the rules object to the validate function the key should be the value of the
name
attribute not the value of theid
as you can see in the example the key isuserEmail
which is the value of the name attribute and theid
is something else
Pros & cons of this approach
- this approach will give us the ability to use more validation rules that require arguments like minlength, remote, equalTo , etc..
- great and manual control over everything
- but the user have to make a separate validate function with different options for every form
Adding or removing dynamic rules
Adding rules
To add a rule we should use the rules method on a jquery elements itself after the form is validated and pass the first parameter the string add
and the second one an object
of rules you want to add for this element (you can also pass a message object for the rules you added)
$('.input').rules('add', {
required: true,
messages: {
required: true,
},
})
Removing rules
if you want to remove a rule or set of rules you pass the string remove
as the first parameter for the rules method then the second will be a string
that containing the rules you want to remove separated by a space
$('.input').rules('remove', 'min max')
More manual approach
accessing the validator object after the form is validated and from it access the rules object and then we can extend or modify it
var validator = $('form').data('validator')
validator.settings.rules.objectName = {
required: true,
}
this approach is very useful if you have an already made rules or messages objects you could extend the rules of the validator
with your own
$.extend(validator.settings, { rules: rules, messages: messages })
to understand the
validator
you can check What exactly happens when we call the validate method section
The validation messages and how they work.
There are 3 ways to provide a validation message
- pass a
messages
object to thevalidate
method the messagesobject
consist of key/value pairs the key is the name of the element and the value is an object containing every rule and its message
$('form').validate({
rules: {
userEmail: {
email: true,
required: true,
},
},
messages: {
userEmail: {
email: 'Please enter your email',
required: '*',
},
},
})
- The value of the
title
attribute on the element
<input id="Email" title="you have to enter a value" type="text" name="Email" />
- default message when defining the validation rule and there are built in default messages for the built in rules
These 3 ways override each other based on the priority, passing the messages object is the most important and the default message is the least important
Add custom validation rules.
When we want to add more validation rules than the default ones we use $.validator.addMethod
this method accepts as parameters the following
- rule name
- a function that do the validation
- a default message
the function that do the validation can be in 2 different signatures
function validationMethod (value, element)
// OR
function validationMethod (value, element, params)
lets explain these parameters
- value: the value of the DOM element that will be validated
- element: the DOM element itself
- params : is what you pass as a value to this validation ruleExample what
params
will equal
$('form').validate({
rules: {
firstname: {
compare: {
type: 'notequal',
otherprop: 'lastname',
},
},
},
})
in this example the params
will equal to
{type:"notequal", otherprop: "lastname"}
Example to add custom rule
$.validator.addMethod(
'notnumbers',
function (value, element) {
return !/[0-9]*/.test(value)
},
'Please don’t insert numbers.'
)
What exactly happens when we call the validate method.
When you call validate
on a form mainly couple of things happens behind the scene
-
Create a
validator
object with all the rules and options and attach it to the form. -
The validate method attaches the validator using $.data , you can get it by selecting the form and calling the jquery $.data function and passing it
validator
. Thevalidator
object is all the metadata for the validation giving us the ability to access the validate options at anytime in the page cycle -
using this object you can change at runtime the options that you passed to the validate method like adding or removing rules, change what happens when the field is valid or invalid or even provide an ignore selector
//getting the validator
var validator = $('.selector').data('validator')
- Note: when you call
validate
on a form that was already validated it will just return the validator object using also $.data and all the options passed to validate method will be omitted
var validator = $('.selector').validate(/* rules will be omitted */)
-
subscribe events to the form itself
-
What will happens when you click submit and there are invalid elements is you will trigger the validation of the fields, if one of them is not valid then the validate plugin will listen to it more closely to check if it is valid or not The events that are subscribed to the form are click, focusin, focusout, keyup, submit
you can disable these events by passing them as keys to the validate method and false as their value
$('.selector').validate({
onfocusout: false,
onkeyup: false,
onclick: false,
onsubmit: false,
})
See also: