Skip to content

Instantly share code, notes, and snippets.

@lkaczanowski
Forked from beccasaurus/README.markdown
Created September 20, 2012 20:36
Show Gist options
  • Save lkaczanowski/3758194 to your computer and use it in GitHub Desktop.
Save lkaczanowski/3758194 to your computer and use it in GitHub Desktop.
Adds hooks to jQuery.validate's form/element validation methods (via trigger())

jQuery Validate Hooks

If you're using ASP.NET MVC3, it uses jQuery Validate to do client-side validations. Instead of using jQuery Validate directly, however, it wraps it with its own jQuery plugin called jQuery.Validate.Unobtrusive. jQuery.Validate.Unobtrusive sets up jQuery Validate for you, behind the scenes, so you don't have an opportunity to customize your jQuery Validate settings at all!

We've been running into trouble with this when we've been doing our own custom client-side validations. We need a way to integrate with the build-in ASP.NET MVC3 validation so we can:

  • Find out when our form's client-side validation runs and do something custom, if it fails
  • Find out when a particular element's client-side validation runs and do something custom if it passes or fails

We might extend this to be able to hook into other things, like jQuery Validate's submitHandler (which allows you to override what happens when the form is valid and ready to be submitted).

Installation

<script type="text/javascript" src="jquery.validate.hooks.js"></script>

Usage

$(document).ready(function(){

  // we're assuming that this has already been run (which MVC3 does automatically)
  // $('form').validate();

  // running this overrides some jQuery Validate stuff so we can hook into its validations.
  // triggerElementValidationsOnFormValidation is optional and will fire off all of your 
  // element validations WHEN the form validation runs ... it requires jquery.validate.unobtrusive
  $('form').addTriggersToJqueryValidate().triggerElementValidationsOnFormValidation();

  // You can bind to events that the forms/elements trigger on validation
  $('form').bind('formValidation', function(event, element, result) {
    console.log(['validation ran for form:', element, 'and the result was:', result]);
  });

  // Or you can use the helper functions that we created for binding to these events
  $('form').formValidation(function(element, result) {
    console.log(['validation ran for form:', element, 'and the result was:', result]);
  });

  $('input.something').elementValidation(function(element, result) {
    console.log(['validation ran for element:', element, 'and the result was:', result]);
  });

  $('input#address').elementValidationSuccess(function(element) {
    console.log(['validations just ran for this element and it was valid!', element]);
  });

  $('input#address').elementValidAndInvalid(function(element) {
    console.log(['validations just ran for this element and it was valid!', element]);
  }, function(element){
    console.log(['validations just ran for this element and it was INVALID!', element]);
  });
});
(function($) {
$.fn.addTriggersToJqueryValidate = function() {
// Loop thru the elements that we jQuery validate is attached to
// and return the loop, so jQuery function chaining will work.
return this.each(function(){
var form = $(this);
// Grab this element's validator object (if it has one)
var validator = form.data('validator');
// Only run this code if there's a validator associated with this element
if (! validator)
return;
// Only add these triggers to each element once
if (form.data('jQueryValidateTriggersAdded'))
return;
else
form.data('jQueryValidateTriggersAdded', true);
// Override the function that validates the whole form to trigger a
// formValidation event and either formValidationSuccess or formValidationError
var oldForm = validator.form;
validator.form = function() {
var result = oldForm.apply(this, arguments);
var form = this.currentForm;
$(form).trigger((result == true) ? 'formValidationSuccess' : 'formValidationError', form);
$(form).trigger('formValidation', [form, result]);
return result;
};
// Override the function that validates the whole element to trigger a
// elementValidation event and either elementValidationSuccess or elementValidationError
var oldElement = validator.element;
validator.element = function(element) {
var result = oldElement.apply(this, arguments);
$(element).trigger((result == true) ? 'elementValidationSuccess' : 'elementValidationError', element);
$(element).trigger('elementValidation', [element, result]);
return result;
};
});
};
/* Below here are helper methods for calling .bind() for you */
$.fn.extend({
// Wouldn't it be nice if, when the full form's validation runs, it triggers the
// element* validation events? Well, that's what this does!
//
// NOTE: This is VERY coupled with jquery.validation.unobtrusive and uses its
// element attributes to figure out which fields use validation and
// whether or not they're currently valid.
//
triggerElementValidationsOnFormValidation: function() {
return this.each(function(){
$(this).bind('formValidation', function(e, form, result){
$(form).find('*[data-val=true]').each(function(i, field){
if ($(field).hasClass('input-validation-error')) {
$(field).trigger('elementValidationError', field);
$(field).trigger('elementValidation', [field, false]);
} else {
$(field).trigger('elementValidationSuccess', field);
$(field).trigger('elementValidation', [field, true]);
}
});
});
});
},
formValidation: function(fn) {
return this.each(function(){
$(this).bind('formValidation', function(e, element, result){ fn(element, result); });
});
},
formValidationSuccess: function(fn) {
return this.each(function(){
$(this).bind('formValidationSuccess', function(e, element){ fn(element); });
});
},
formValidationError: function(fn) {
return this.each(function(){
$(this).bind('formValidationError', function(e, element){ fn(element); });
});
},
formValidAndInvalid: function(valid, invalid) {
return this.each(function(){
$(this).bind('formValidationSuccess', function(e, element){ valid(element); });
$(this).bind('formValidationError', function(e, element){ invalid(element); });
});
},
elementValidation: function(fn) {
return this.each(function(){
$(this).bind('elementValidation', function(e, element, result){ fn(element, result); });
});
},
elementValidationSuccess: function(fn) {
return this.each(function(){
$(this).bind('elementValidationSuccess', function(e, element){ fn(element); });
});
},
elementValidationError: function(fn) {
return this.each(function(){
$(this).bind('elementValidationError', function(e, element){ fn(element); });
});
},
elementValidAndInvalid: function(valid, invalid) {
return this.each(function(){
$(this).bind('elementValidationSuccess', function(e, element){ valid(element); });
$(this).bind('elementValidationError', function(e, element){ invalid(element); });
});
}
});
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment