jQuery Validation: Changing Rules Dynamically

JqueryJquery Validate

Jquery Problem Overview


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?

Jquery Solutions


Solution 1 - Jquery

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 - Jquery

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 - Jquery

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 - Jquery

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

Solution 5 - Jquery

try this..

rules: {
    address: {
       required: {
                   depends: function(element) {
                     if (....){
                       return true;}
                     else{
                       return false;}
                   }
                 }
             }
       }

credit from here.

Solution 6 - Jquery

There is an option now to ignore fields bases on selector criteria, such as invisible or disabled, such that you wouldn't have to change your rule set:

.validate({
  ignore: ":not(:visible),:disabled",
  ...

Solution 7 - Jquery

Keep track of the validation object and remove/replace rules directly. Works for me with v1.13.0

var validation = $('#form1').validate(); //Keep track of validation object

//Rule set 1
var validationRulesLogin = {
	headerEmail: {
		required: true,
		email: true
	},
	headerPassword: "required"
};
var validationMessagesLogin = {
	headerEmail: {
		required: "Please enter your email address.",
		email: "Not a valid email address."
	},
	headerPassword: "Please enter your password."
};

//Rule set 2
var validationRulesSignup = {
	signupEmail: {
		required: true,
		email: true
	},
	signupPassword: "required",
	signupPassword2: {
		equalTo: "#phBody_txtNewPassword"
	}
};
var validationMessagesSignup = {
	signupEmail: {
		required: "Please enter your email address.",
		email: "Not a valid email address."
	},
	signupPassword: "Please enter your password.",
	signupPassword2: "Passwords are not the same."
};

//Toggle rule sets
function validatingLoginForm(){
	validation.resetForm();
	validation.settings.rules = validationRulesLogin;
	validation.settings.messages = validationMessagesLogin;
}
function validationSignupForm(){
	validation.resetForm();
	validation.settings.rules = validationRulesSignup;
	validation.settings.messages = validationMessagesSignup;
}

Solution 8 - Jquery

Take a look at my answer https://stackoverflow.com/a/20547836/1399001. It includes a working jsfiddle. In your example will be something like this:

$("input[name='userAction']").change(function() {

    var settings = $("#myForm").validate().settings;

      if ($("input[name='userAction']:checked" ).val() === "login") {
            $.extend(settings, {
              rules: loginRules
            });
    } else {
            $.extend(settings, {
              rules: signupRules
            });
    }


    $("#myForm").valid();

});

Solution 9 - Jquery

I had a similar problem and solved it by adding a "requiredForLogin" class to all of the login textboxes, and "requiredForSignUp" class to all of the signup textboxes.

Then used jQuery's toggleClass, and jQuery.validate's addClassRules to turn on and off the rules depending on which button was pressed.

function EnableAllValidation() {
	// remove the jquery validate error class from anything currently in error
	//  feels hackish, might be a better way to do this
	$(".error").not("label").removeClass("error");

	// remove any the 'disabled' validation classes, 
	//  and turn on all required validation classes 
	//  (so we can subsequently remove the ones not needed)
	$(".requiredForLoginDisabled").toggleClass("requiredForLoginDisabled requiredForLogin");
	$(".requiredForSignUpDisabled").toggleClass("requiredForSignUpDisabled requiredForSignUp");
}
function EnableLoginValidation() {
	// reenable all validations
	//  then disable the signUp validations
	EnableAllValidation();
	$(".requiredForSignUp").toggleClass("requiredForSignUpDisabled requiredForSignUp");
}
function EnableSignUpValidation() {
	// reenable all validations
	//  then disable the login validations
	EnableAllValidation();
	$(".requiredForLogin").toggleClass("requiredForLoginDisabled requiredForLogin");
}
$(document).ready(function () {
	$("input[value='login']").click(function () {
		EnableLoginValidation();
	});
	$("input[value='signup']").click(function () {
		EnableSignUpValidation();
	});

	$("#myForm").validate();
	jQuery.validator.addClassRules({
		requiredForSignUp: {
			required: true
		},
		requiredForLogin: {
			required: true
		}
	});

});

Solution 10 - Jquery

This can be easily done by updating the .validate().settings.rules

Example snippet below for password field which will be added with required rule.

$('#myForm').validate().settings.rules.password = {required: true};

Solution 11 - Jquery

the below code is working superb...

.validate({
  ignore: ":not(:visible),:disabled",
  ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBullinesView Question on Stackoverflow
Solution 1 - JqueryRyleyView Answer on Stackoverflow
Solution 2 - JqueryrobertView Answer on Stackoverflow
Solution 3 - JqueryFlavioEscobarView Answer on Stackoverflow
Solution 4 - JqueryBoban StojanovskiView Answer on Stackoverflow
Solution 5 - JquerywwanichView Answer on Stackoverflow
Solution 6 - JqueryjeeberView Answer on Stackoverflow
Solution 7 - JqueryDanView Answer on Stackoverflow
Solution 8 - Jquerylboullo0View Answer on Stackoverflow
Solution 9 - JqueryJPuchyrView Answer on Stackoverflow
Solution 10 - JqueryMichael YohanesView Answer on Stackoverflow
Solution 11 - JqueryLingeshView Answer on Stackoverflow