Author: Andrew Bond
While doing some bug fixing and cleanup in a web application, I had the chance to go a little deeper into the jQuery user input validation framework. There are many tutorials available about implementing custom validations. But what I wanted to do was to extend the default validations with my own code, while preserving the existing functionality, and to do it site-wide.
So let’s pretend that I’d like to extend the default “required” validation in such a way that you are not allowed to enter “foo” in any form field with the “required” class. First, I need to write a function to test this:
function notFoo(value) {
return value !== "foo";
}
Putting the custom code in a separate function makes it very easy to unit test.
Now, I’d like to replace the default “required” validation with one which first calls my custom method, and then does the regular, default validation, if it passes the custom validation. I can call jQuery.validator.addMethod, and pass “required” as the name argument. Even though this is a standard validator, supplied by the jQuery validation framework, I’m allowed to replace it with my own custom method:
jQuery.validator.addMethod("required", function(value, element, param) {
return notFoo(value);
},
jQuery.validator.messages.required // use default message
);
So far, I’ve only replaced the standard “required” validator. This is useful by itself; there may be times when you want to write code to completely replace the standard validator. If you put this code in your site master template, you will have accomplished that goal.
But my goal was to extend the default validation, not replace it. So I need to store a reference to the default “required” validator, and then call it, after calling my custom code:
jQuery.validator.methods.oldRequired = jQuery.validator.methods.required;
jQuery.validator.addMethod("required", function(value, element, param) {
if (!notFoo(value)) {
return false;
}
return jQuery.validator.methods.oldRequired.call(this, value, element, param);
},
jQuery.validator.messages.required // use default message
);
I can’t call the oldRequired method directly, because it uses “this“, which will point at the wrong thing if I just invoke it without call.
Before I wrap up this post, I would like to extend thanks to the folks at Stack Overflow who helped me fix a some issues in my first attempt at doing this.