benino
benino

Reputation: 597

jQuery Validation Plugin - adding rules that apply to multiple fields

I'm using the jQuery Validation plugin:

I have several fields in a large form that I want to apply the same rules to. I've simplified the code for this example. This code doesn't work, but I want to do something like this. The second rule should apply to both first_name and last_name. I want to encapsulate all the rules here in this function and not edit the class lists of some of the form elements to add a required class or whatever.

(Again, I have several different groups of form fields with different requirements that I want to group. I only put required: true in that element for simplicity)

$('#affiliate_signup').validate(
       {
          rules: 
          {
            email: {
                required: true,
                email: true
            },
            first_name,last_name: {
                required: true
            },
            password: {
                required: true,
                minlength: 4
            }
          }
       });

Thanks in advance.

Upvotes: 35

Views: 47380

Answers (3)

alpham8
alpham8

Reputation: 1362

If I understood you right, you want to apply many rules to many fields, that may differ at some rules, but you are too lazy to repeat yourself with the same rules to other fields. However, with jQuery validate it's possible to have more than one rule on one input field. Just use the array notation here.

To achieve your use case, just add data attributes to each input field with the rules you want to apply to it. In best case, use an url encoded json format, so that you just need one data attribute per each input field. E. g.:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>validate test</title>
</head>
<body>
<form id="myForm" name="myForm" method="post" action="www.example.com/my-url">
    <input type="text" name="txt1" data-rules="%7B%22required%22%3Atrue%2C%22minlength%22%3A2%2C%22maxlength%22%3A10%7D" />
    <input type="text" name="txt2" data-rules="%7B%22required%22%3Atrue%2C%22minlength%22%3A2%2C%22maxlength%22%3A10%7D" />
    <input type="number" name="number1" data-rules="%7B%22required%22%3Atrue%2C%22number%22%3Atrue%2C%22min%22%3A1%2C%22max%22%3A999%7D" />
    <input type="email" name="email1" data-rules="%7B%22required%22%3Atrue%2C%22email%22%3Atrue%2C%22minlength%22%3A20%7D" />
    <input type="email" name="email2" data-rules="%7B%22required%22%3Atrue%2C%22email%22%3Atrue%2C%22minlength%22%3A20%7D" />
</form>
<script type="text/javascript">
    var $field = null;
    var rules = {};

    $('#myForm input, #myForm textarea').each(function (index, field) {
        $field = $(field);
        rules[$field.attr('name')] = JSON.parse(decodeURIComponent($field.attr('data-rules')));
    });

    $('#myForm').validate(rules);
</script>
</body>
</html>

The basic technology behind that is simple:

  1. Create your fields with the `data-`` attribute.
  2. Loop over each input field to grab the rules that you want to apply on it.
  3. Apply your collected rules to the form element

You could also use input groups with the same validators that way, e. g. by using classes for it and predefined JavaScript variables with the rules object. I think you got the idea on how to get lazy in an elegant way ;-)

Upvotes: 0

Antonio Clemente
Antonio Clemente

Reputation: 1

You can use the 'getter' syntax in this way:

   {
      rules: 
      {
        email: {
            required: true,
            email: true
        },

        first_name: {
            required: true
        },

        get last_name() {return this.first_name},

        password: {
            required: true,
            minlength: 4
        }
      }
   }

Upvotes: 0

Sparky
Sparky

Reputation: 98748

For the purposes of my example, this is the base starting code:

HTML:

<input type="text" name="field_1" />
<input type="text" name="field_2" />
<input type="text" name="field_3" />

jQuery:

$('#myForm').validate({
    rules: {
        field_1: {
            required: true,
            number: true
        },
        field_2: {
            required: true,
            number: true
        },
        field_3: {
            required: true,
            number: true
        }
    }
});

http://jsfiddle.net/9W3F7


Option 1a) You can pull out the groups of rules and combine them into common variables.

var ruleSet1 = {
        required: true,
        number: true
    };

$('#myForm').validate({
    rules: {
        field_1: ruleSet1,
        field_2: ruleSet1,
        field_3: ruleSet1
    }
});

http://jsfiddle.net/9W3F7/1


Option 1b) Related to 1a above but depending on your level of complexity, can separate out the rules that are common to certain groups and use .extend() to recombine them in an infinite numbers of ways.

var ruleSet_default = {
        required: true,
        number: true
    };

var ruleSet1 = {
        max: 99
    };
$.extend(ruleSet1, ruleSet_default); // combines defaults into set 1

var ruleSet2 = {
        min: 3
    };
$.extend(ruleSet2, ruleSet_default); // combines defaults into set 2

$('#myForm').validate({
    rules: {
        field_1: ruleSet2,
        field_2: ruleSet_default,
        field_3: ruleSet1
    }
});

End Result:

  • field_1 will be a required number no less than 3.

  • field_2 will just be a required number.

  • field_3 will be a required number no greater than 99.

http://jsfiddle.net/9W3F7/2


Option 2a) You can assign classes to your fields based on desired common rules and then assign those rules to the classes. Using the addClassRules method we're taking compound rules and turning them into a class name.

HTML:

<input type="text" name="field_1" class="num" />
<input type="text" name="field_2" class="num" />
<input type="text" name="field_3" class="num" />

jQuery:

$('#myform').validate({ // initialize the plugin
    // other options
});

$.validator.addClassRules({
    num: {
        required: true,
        number: true
    }
});

http://jsfiddle.net/9W3F7/4/


Option 2b) The main difference from option 2a is that you can use this to assign rules to dynamically created input elements by calling rules('add') method immediately after you create them. You could use class as the selector, but it's not required. As you can see below, we've used a wildcard selector instead of class.

The .rules() method must be called any time after invoking .validate().

jQuery:

$('#myForm').validate({
    // your other plugin options
});

$('[name*="field"]').each(function() {
    $(this).rules('add', {
        required: true,
        number: true
    });
});

http://jsfiddle.net/9W3F7/5/


Documentation:

Upvotes: 104

Related Questions