17

I've a form where I'm having some fields and then if needed user can add more fields of same type. Im using http://jqueryvalidation.org/ validate plugin to validate fields.

As I read somewhere jquery validate plugin requires unique names to fields for validating them. So i'm naming each field uniquely. First I hoped that validate plugin will take care of dynamically added element's validation if I add rules using classes. But it turns out it does not.

So even if name of each field is unique, validate plugin validates only first input which was rendered initially.

I even tried using $.clone() in hope that it'll take care of all event bindings. But it did not worked for me. So I moved to underscore to repeat the markup as there are number of fields and I don't want to write templates in JS and name accordingly.

I can't find a solution to this and stuck here. Can't more on until this issue is resolved.

Here's JS that I've written.

$("#work_form").validate();

$(".work_emp_name").rules("add", {
    required: true
});

_.templateSettings.variable = "element";
var tpl = _.template($("#form_tpl").html());

var counter = 1;

$("form").on("click", ".add_employer", function (e) {
    e.preventDefault();
    var tplData = {
        i: counter
    };
    $("#word_exp_area").append(tpl(tplData));
    counter += 1;
});

Please find markup in fiddle set up.

example and code set up here

Sparky
  • 98,165
  • 25
  • 199
  • 285
SachinGutte
  • 6,947
  • 5
  • 35
  • 58

3 Answers3

36

When using one of the methods from this plugin, like .rules(), and targeting more than one element, like a class, you must also use the jQuery .each() method.

$('.work_emp_name').each(function () {
    $(this).rules("add", {
        required: true
    });
});

And you cannot use .rules() on elements that don't yet exist in the DOM. Simply move the .rules() method to inside the function that creates your new inputs.

$("form").on("click", ".add_employer", function (e) {
    e.preventDefault();
    var tplData = {
        i: counter
    };
    $("#word_exp_area").append(tpl(tplData));
    counter += 1;
    $('.work_emp_name').each(function () { 
        $(this).rules("add", {
            required: true
        });
    });
});

Working DEMO: http://jsfiddle.net/Yy2gB/10/


However, you can make it more efficient by only targeting the one new field, instead of all fields with the work_emp_name class.

$("form").on("click", ".add_employer", function (e) {
    e.preventDefault();
    var tplData = {
        i: counter
    };
    $("#word_exp_area").append(tpl(tplData));   // <- add new field
    $('input[name="work_emp_name['+counter+']"]').rules("add", {  // <- apply rule to new field
        required: true
    });
    counter += 1;
});

Working DEMO: http://jsfiddle.net/Yy2gB/11/


Both of my examples above are for adding rules to the dynamically created fields. You'll still need to declare any rules for your static fields upon dom ready as follows...

$("#work_form").validate({
    rules: {
        "work_emp_name[0]": {
            required: true
        }
    }
});
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • 2
    just to save the time (or for now) I just added `data-rule-required="true"` in template itself. This also forces validation rules on dynamic elements. And I'm having like 8 fields which gets repeated on single click of `Add Employer` button ( designation, scope of work, start & end date, appointment letters and so on). So if I want to add rules to these fields as well then I'd have to write same code in `Add Employer` click listener. It's too much. Instead I chose data attributes method to add validation rules. – SachinGutte Dec 14 '13 at 07:18
  • But adding rules via data attributes does not give more control like if there are any fields that are depend on values of other fields. So your answer does fits all those scenarios as well and gives more control. So it's correct way. Thank you for taking time to solve this. – SachinGutte Dec 14 '13 at 07:20
  • 3
    Maybe it's vague question but isn't a plugin like validate should take care of dynamically added fields or adding rules with classes w/o using `$.each` in first place ? Now I know it's written quite great and have many options but I mean these are basic things that a plugin should be having. – SachinGutte Dec 14 '13 at 19:01
  • @SachinG, that's up to each developer. For this plugin, you must you `.each()`. – Sparky Dec 14 '13 at 19:57
  • Can you please expand your answer to show how a custom validation message can be set for these dynamic rules? – geoidesic Apr 02 '16 at 10:02
  • @geoidesic, the OP did not ask for that. Please see examples in the documentation for changing messages using the `.rules()` method. – Sparky Apr 02 '16 at 21:53
  • How to add a function to remove the last add field decrementing? Thanks – user3631428 Jan 19 '17 at 05:58
  • @user3631428, please post a new question rather than within comments. – Sparky Jan 19 '17 at 14:29
  • If you add array like fields with a same name then the validation don't work. There is an open issue: https://github.com/jquery-validation/jquery-validation/issues/1774 – Jordan Enev Mar 15 '17 at 11:28
3

Returns the validations rules for the first selected element or Adds the specified rules and returns all rules for the first matched element. Requires that the parent form is validated, that is, $( “form” ).validate() is called first or

Removes the specified rules and returns all rules for the first matched element. more info

function addRule(id){
    $("[name='work_emp_name["+id+"]']").rules("add", {
        required: true
    });
}
$("#work_form").validate();
addRule(0);

_.templateSettings.variable = "element";
var tpl = _.template($("#form_tpl").html());

var counter = 1;

$("form").on("click", ".add_employer", function (e) {
    e.preventDefault();
    var tplData = {
        i: counter
    };
    $("#word_exp_area").append(tpl(tplData));
    addRule(counter);
    counter += 1;
}); here
nzn
  • 828
  • 5
  • 12
  • Right idea but seems a little more verbose than necessary. – Sparky Dec 13 '13 at 22:35
  • @Sparky in this jsfiddle.net/Yy2gB/9 your example basically you did same thing what i, just it will work only on new elements, not on existing ones. – nzn Dec 13 '13 at 23:41
  • My oversight. The existing one can be declared when the page is initialized or via inline HTML. Fixed my answer. Thanks. – Sparky Dec 14 '13 at 00:59
  • What helped me was `Requires that the parent form is validated...` It's critical to run `.validate()` on the form before adding the rules, otherwise it won't work. Thanks, @nzn – Alex Apr 12 '17 at 17:15
1

That's because jQuery Validation only validates the first occurrence of the array currently.

You can check my commit on the plugin that will just work fine on any occurrence of the named array.

Saurabh Sharma
  • 2,422
  • 4
  • 20
  • 41