3

Looking at the documentation here: http://docs.jquery.com/Plugins/Validation/Reference#Fields_with_complex_names_.28brackets.2C_dots.29 the syntax for attaching rules to input arrays is like this:

rules: {
"user[email]": "email",

However in my case the array keys are number values and could have any value, but still I'd like to attach the rule to the fields. I dynamically add input fields with jQuery (key is a global variable):

 $('a#addfield').click(function(e)
 {
    e.preventDefault();
    var data = '<p><input type="file" name="field['+key+']"></p>';
    $('div#inputcontainer').append(data);
 });

Sample HTML output:

<p><input name="field[19]" type="file"></p>
<p><input name="field[22]" type="file"></p>
<p><input name="field[25]" type="file"></p>

I have tried defining the rules like this:

rules: 
{
   'field[]': {
         required: true,
         extension: "pdf|doc|docx"
    }
}

(taken from this answer: jquery validate add rules for an array input EDIT: This suggested way of setting rules with 'field[]' is not working with the validation plugin. See answer and comments below. )

But there is no validation error when I try to add other filetypes... Any suggestions?

4
  • From what I remember, jQuery.validate does not support validation of multiple fields with the same name like that, not even if you'd remove the numbers between brackets (which you can do when sending it to most back-end languages). Try using $('input').rules("add", { required:true, extension: "pdf|docx?" }) Commented Mar 12, 2013 at 13:56
  • Thanks! The input fields are added dynamically so I can't use your suggestion as the inputs are not in DOM. Also I'm using the array key to keep track of many things in the form so I can't just set name="field[]" which would work with the validation... Commented Mar 12, 2013 at 14:01
  • Use .rules("add", {}) for each dynamically generated field. There is no other option that doesn't involve uglier hacks. Commented Mar 12, 2013 at 14:02
  • Thanks. It worked. Add as your answer and I will accept. My solution was to add the rule for each dynamically added inputfield: $('input[name="field['+key+']"]').rules("add", { required:true, extension: "pdf|doc|docx" }); (key was my variable with the number...) Commented Mar 12, 2013 at 14:06

3 Answers 3

2

You can apply .rules("add", rules) to each generated element:

$(element).rules("add", { required:true, extension: "pdf|docx?" });

jQuery.validate does provide a way to validate elements with the same name (foo[] nor foo[N]) through the rules set on a form (at least up to v1.11).

There are some other ways for adding dynamic rules, for example, to add a required check without calling .rules('add') you can simply use class="required" in the element and the validation plugin should pick it up dynamically.

However, there is no built-in equivalent to the extension option so you'd have to add a class to all inputs and create your own class rules with addClassRules. This ends up mixing a bit of behavior with HTML and possibly CSS though.


Note for future readers: both .rules('add') and addClassRules do not work for repeated names (e.g. foo[]) but these do work if the name is not exactly the same (e.g. foo[index]) which is OP's case.

I believe inputs with the exact same name is off-topic for this question, but for these you either have to add your own validation method with addMethod, or add your own validation inside the form's submit handler or try this related answer.

Sign up to request clarification or add additional context in comments.

13 Comments

@jtheman In regex, ? makes the character preceding it optional.
Yes I know about setting the class="required", I was also considering a solution to use addMethod() to add a custom method to validate the extension. Probably possible too?
@jtheman Yes it is possible. =] addMethod is very handy if you need some custom validation.
@jtheman Yes, I never got that syntax to work. It gives a false impression that it is working because the validation picks in the first element, but not the rest if you have more than one with the same name.
@jtheman, Yes, in general "chameleon-questions" are a bad practice. However, in this case, simply editing your modest clarifications into your question would have been preferred over placing them in comments. Otherwise, one answer may be more relevant to solving your problem than a different answer that's more relevant to your OP.
|
1

I think the answer given is right, but it is also worth considering creating a class rule combining your two rules, then give your inputs this class. That way you don't have to call addMethod each time you dynamically add a new element to the DOM.

$.validator.addClassRules("myinput", { required:true, extension: "pdf|docx?" });

html

<input name="field[19]" type="file" class="myinput"> 
<input name="field[22]" type="file" class="myinput"> 
<input name="field[25]" type="file" class="myinput">

1 Comment

Thanks, this was what I initially was looking for! However now I stick to the previous solution (noone is paying me for changing it again...) :D +1 to you!
1

EDIT: My answer was posted on the original version of the question, where without reading comments, it was unknown that these fields are dynamically created. Otherwise, it may be preferred to simply add the rules as each field is created:

var myRule = { // save some code... put the common rule into a variable
    required:true,
    extension: "pdf|docx?"
};

$('a#addfield').click(function(e) {
    e.preventDefault();
    var data = '<p><input type="file" name="field['+key+']"></p>';
    $('div#inputcontainer').append(data);
    $('[name="field['+key+']"]').rules("add", myRule); // add the rule to the new field
});

(Nested brackets handled as per this answer.)

original answer follows:


The accepted answer gets you halfway there.

Also, my answer does not require an additional class or any other changes to your existing HTML structure. This is all jQuery...

The first half is to use the built-in rules('add') method.

$(element).rules("add", {
    required:true,
    extension: "pdf|docx?"
});

The second half is to get that method applied to all elements with named "field[19]", "field[20]", "field[21]", etc.

You simply use a jQuery .each() with a jQuery "starts with" selector.

$('[name^="field"]').each(function() {
    $(this).rules("add", {
        required:true,
        extension: "pdf|docx?"
    });
});

DEMO: http://jsfiddle.net/cWABL/

11 Comments

Remember that fields are added dynamically. With this, if you plan to use this code whenever an input is added, you'd query the DOM multiple times unnecessarily re-adding rules that already exist for those elements.
@FabrícioMatté, you are correct. However, my answer only applies to the OP as it's presently written. If the OP could show the code that actually adds the field, perhaps a better answer can be provided.
Yes, your answer can help future visitors that have an issue to similar to the questioner's code. As for dynamically generated inputs that OP has, it is just a simple matter of replacing the loop with applying the .rules('add') to each generated input.
@jtheman, I'm glad you got it figured out. I posted my answer, after you accepted the other, mostly as a service to the casual reader who may simply take the OP as written, without reading the comments. Thank-you!
@jtheman, and in that same spirit, I've edited my answer to be more relevant to your specific situation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.