jQuery Validation: Changing Rules Dynamically

I have a single form that, depending on which radio button is clicked (Login or Signup), displays either:

  • email address
  • password

or:

  • name
  • age
  • email address
  • password

Clicking on the radio button toggles the visibility of the Login/Signup fields:

<form id="myForm">
    <input name="userAction" type="radio" value="login" checked="checked">Login</input>
    <br />
    <input name="userAction" type="radio" value="signup">Sign Up</input>

    <div id="loginFields" style="display:none">
        <!-- Login fields (email address and password) -->
    </div>

    <div id="signupFields" style="display:none">
        <!-- Signup fields (name, age, email address, password) -->
    </div>
</form>

I'm using the jQuery Validation plug-in, and I'd like to use the following rules:

var signupRules = {
    emailAddressTextBox:
    {
        required: true,
        email: true 
    },
    passwordTextBox:
    {
        required: true,
        minlength: 6,
        maxlength: 24,
        passwordValidationRule: true // custom regex added with $.validator.addMethod()
    }
};

var loginRules = {
    nameTextBox:
    {
        required: true,
        maxlength: 50
    },
    loginEmailAddressTextBox:
    {
        required: true,
        email: true 
    },
    loginPasswordTextBox:
    {
        required: true,
        minlength: 6,
        maxlength: 24,
        passwordValidationRule: true // custom regex added with $.validator.addMethod()
    },
    loginPasswordAgainTextBox:
    {
        required: true,
        minlength: 6,
        maxlength: 24,
        equalTo: "#loginPasswordTextBox"
        passwordValidationRule: true // custom regex added with $.validator.addMethod()        
    }
};

How can I add the correct validation rule dynamically based on:

   $("input[name='userAction']").change(function() {
        if ($("input[name='userAction']:checked" ).val() === "login") {
            // use loginRules
        } else {
            // use signupRules
        }
    });

I've tried the following:

$("#myForm").validate({
    rules: ($("input[name='userAction']:checked" ).val() === "login") ? loginRules : signupRules;
});

But since my Login fields are the default displayed, its validations work, but the Signup scenario doesn't; it wants to validate Login fields for some reason. Am I missing something?


Solution 1:

Ahh validation plugin, always so tricky :(

First, I added id attributes to all the input boxes. Then, I made a change function for you:

$("input[name='userAction']").change(function() {
    $('#signupFields').toggle();
    $('#loginFields').toggle();    
    if ($("input[name='userAction']:checked").val() === "login") {
        removeRules(signupRules);
        addRules(loginRules);
    } else {        
        removeRules(loginRules);
        addRules(signupRules);

    }
});

The add and remove functions look like this:

function addRules(rulesObj){
    for (var item in rulesObj){
       $('#'+item).rules('add',rulesObj[item]);  
    } 
}

function removeRules(rulesObj){
    for (var item in rulesObj){
       $('#'+item).rules('remove');  
    } 
}

That's pretty much it. See here for a working example: http://jsfiddle.net/ryleyb/wHpus/66/

EDIT: To me, the non-intuitive part is that I don't see an easy way to add/remove rules to the whole form after you call validate, instead you have to manipulate the individual form elements.

Solution 2:

Or you can use the depends property.

http://jqueryvalidation.org/category/plugin/ search for depends

Example: Specifies a contact element as required and as email address, the latter depending on a checkbox being checked for contact via email.

$(".selector").validate({
  rules: {
    contact: {
      required: true,
      email: {
        depends: function(element) {
          return $("#contactform_email:checked")
        }
      }
    }
  }
});

Solution 3:

This post is from years ago, but since it has been viewed a lot of times, I think it would be useful to say that the jQuery Validation plugin now allows us to read, add and remove rules.

Some examples:

  1. Print all rules attached to #myField: console.log($('#myField').rules());

  2. Remove an unwanted rule: $('#myField').rules('remove', 'min');

  3. Add a new rule: $('myField').rules('add', {min: 10});

So say if you want to dynamically update the minimum value required. You can call a remove and a add right after:

// Something happened. The minimum value should now be 100
$('#myField').rules('remove', 'min');
$('#myField').rules('add', {min: 100});

More information can be found here: https://jqueryvalidation.org/category/plugin/#-rules()

Solution 4:

If you want to call validate again with new settings (rules,messages ... etc.) call

$('#formid').removeData('validator')

This will remove validation for the form then initialize it again with the new settings