Checkbox has to be ‘checked’ – with unobtrusive jQuery validation and ASP.NET MVC 3


Is it a pretty common scenario to have a checkbox on a form, that is required to be checked during POST-ing of a form. This usually happens when we have a typical ‘Agree to Terms and Conditions’ element. When I started to play with unobtrusive JavaScript validation in new ASP.NET MVC i was pretty sure that decorating boolean property with [Required] attribute will solve that issue. Surprisingly it doesn’t.

The key to this problem lies in interpretation of jQuery validation ‘required’ rule. I digged a little and find a specific code inside a jquery.validate.unobtrusive.js file:

adapters.add("required", function (options) {
  // jQuery Validate equates "required" with "mandatory" for checkbox elements
  if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
    setValidationValues(options, "required", true);
  }
});

As You can see rule does not applies to checkboxes. Simple solution to that would be to either change this code (which we really do not want to do) or create a new specific adapter. I do not know why it is like that – i can guess that it might be for a backward compatibility. Anyway, to make that work we will start by creating a custom attribute.

public class BooleanRequired : RequiredAttribute, IClientValidatable {        

        public BooleanRequired() {

        }

        public override bool IsValid(object value) {
            return value != null && (bool)value == true;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
            return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = "brequired", ErrorMessage = this.ErrorMessage } };
        }
    }

As You can see it inherits from common RequiredAttribute. Moreover it implements IClientValidateable. This is to make assure that rule will be propagated to client side (jQuery validation) as well. The key part here is GetClientValidationRules method (adapter) where we define new, custom ValidationType called for the purpose of this post, as a ‘brequired’. To make that work, a specific JavaScript code has to be prepare that adds our custom adapter:


jQuery.validator.unobtrusive.adapters.add("brequired", function (options) {
    //b-required for checkboxes
    if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
        //setValidationValues(options, "required", true);
        options.rules["required"] = true;
        if (options.message) {
            options.messages["required"] = options.message;
        }
    }
});

All that is left is to mark properties with newly created BooleanRequired attribute.


[BooleanRequired]
public bool AcceptTermsAndCond { get; set' }

Happy coding!

Share

Related posts:

  1. Tips for jQuery validation plugin
  2. Client side validation after Ajax Partial View result in ASP.NET MVC 3
  3. Validate max file size during upload in asp.net mvc
  4. jQuery style Ui dialog over flash banners
  5. Firefox 3.0: 411 Length required with JQuery
  • JK

    Any chance you could post a sample of this working with the newer entity framework? That would be great!

  • JK

    Nevermind. I figured it out. Great post!

  • http://www.getcheapflowers.co.uk Cheap Flower Guy

    You can simply your javascript to just: (function ($) {
    $.validator.unobtrusive.adapters.addBool(“mandatory”, “required”);
    } (jQuery));

  • http://www.getcheapflowers.co.uk Cheap Flower Guy

    Oops. I meant : (function ($) {
    $.validator.unobtrusive.adapters.addBool(“brequired”, “required”);
    } (jQuery));

  • http://www.yairtvaor.com Yair Tavor

    In the BooleanRequired class, you return the error message as

    return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = “brequired”, ErrorMessage = this.ErrorMessage } };

    but if you use Global resources to supply the message the this.ErrorMessage will be null.

    It’s better to return the this.ErrorMessageString which takes to account the resource error message.

    Also, in order to avoid the redundant new ModelClientValidationRule[]{} you can just use

    yield return new ModelClientValidationRule() { ValidationType = “brequired”, ErrorMessage = this.ErrorMessageString };

  • Sebastian

    This method is working great for me. thank you!!

  • Madhu

    Hi,

    This was really helpful. I have another scenario in which I have to check if atleast one checkboxes is checked out of the two check boxes I have and then submit the form. I searched a lot on this issue but couldn’t get a clear picture. Can you help me on this?

    Thanks.

  • René Titulaer

    Hello,

    this doesn’t work for me.

    The server side part works well. But the client side code doesn’t kick in before submit.

    I use IE8, any ideas?

  • René Titulaer

    It does work now.
    There was something strange going on with my javascript includes.
    In the layout page I included (will be rendered in the head section):
    jquery-1.5.1.js
    jquery.unobtrusive-ajax.min.js
    jquery.validate.js
    jquery.validate.unobtrusive.js

    In the page I included (will be rendered in the body):
    jquery.unobtrusive-ajax.min.js
    jquery.validate.js
    jquery.validate.unobtrusive.js

    Because I didn’t include jquery-1.5.1.js in the page it didn’t work for me.

    Now I removed the javascript includes in the page (because they were added twice anyway) and now it works.
    I don’t understand why it doesn’t works when I include files twice. Doesn’t matter, they only have to be include onced of course so now it’s solved.

  • Nirman Doshi

    Nice article. Excellent writeup and easy to understand.
    Quite informative

  • Indrajith

    Awesome writing !!! worked like a charm…

  • Iris Pintos

    Great article! Help me so much :)