42

Am new to jquery validation plugin but i would like to know how do we validate array of input boxes using validation plugin..

Below is html code.

<form id="transport-form">
  <input type="text" name="qty[]" id="qty1">
  <input type="text" name="qty[]" id="qty2" >
  <input type="text" name="qty[]" id="qty3">
  <input type="text" name="qty[]" id="qty4">
  <input type="submit value="submit">
</form>

and jquery code is below

jQuery("#transport-form").validate({
        rules: {
            'qty[]': {
                required: true
            }
        },
    });

But everytime i click submit it is validating only the first value. rest all the values of same name are not validated. Please help.

Sparky
  • 98,165
  • 25
  • 199
  • 285
Amit
  • 3,251
  • 3
  • 20
  • 31
  • Why does your input have the same name? I dont know if that is valid, but I think only the first input will have set that `qty[]` name – bumbumpaw Jul 10 '14 at 07:11
  • these are dynamically generated using ajax also they have common name because it will be easy to save data at the server side. Is it not right to use same name?? – Amit Jul 10 '14 at 07:14
  • 1
    hmm, not sure .but based on my experience, it will not work. try it. It will only be set on the first occurence of the name. – bumbumpaw Jul 10 '14 at 07:19
  • really late to this party, but names such are used `qty[]` to represent arrays. It IS valid HTML – Ramses Nov 10 '22 at 17:20

12 Answers12

71

Sometimes we need to validate an array of input elements: For example –

<form name="signupForm" class="cmxform" id="signupForm" method="get" action="">
    <select name="category[]" id="cat_1">
    <option value="">Select One</option>
    <option value="1">aa</option>
    <option value="2">bb</option>
    <option value="3">cc</option>
    <option value="4">dd</option>
    </select>

    <select name="category[]" id="cat_2">
    <option value="">Select One</option>
    <option value="5">ee</option>
    <option value="6">ff</option>
    <option value="7">gg</option>
    <option value="8">hh</option>
    </select>

    <select name="category[]" id="cat_3">
    <option value="">Select One</option>
    <option value="9">ii</option>
    <option value="10">jj</option>
    <option value="11">kk</option>
    <option value="12">ll</option>
    </select>

    <input class="submit" type="submit" value="Submit">
    </form>

Now we will use jquery validation plugin jquery.validate.js for validating the form. The condition will be that user will have to choose category from each dropdown. The script for validation will be as below -

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.validate.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
    // validate the comment form when it is submitted
    $("#signupForm").validate({
        rules: {
            "category[]": "required"
        },
        messages: {
            "category[]": "Please select category",
        }
    });
});
</script>

Now the problem is that the readymade jquery.validate.js only validates the first element of category[]. So, we need to modify it a little bit.

In jquery.validate.js, we can find a function named checkForm, we have to modify it as below:

checkForm: function() {
    this.prepareForm();
    for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) {
        if (this.findByName(elements[i].name).length != undefined && this.findByName(elements[i].name).length > 1) {
            for (var cnt = 0; cnt < this.findByName(elements[i].name).length; cnt++) {
                this.check(this.findByName(elements[i].name)[cnt]);
            }
        } else {
            this.check(elements[i]);
        }
    }
    return this.valid();
}

I just got this solution from http://www.codeboss.in/web-funda/2009/05/27/jquery-validation-for-array-of-input-elements/ hope this helps someone..

AsgarAli
  • 2,201
  • 1
  • 20
  • 32
Amit
  • 3,251
  • 3
  • 20
  • 31
  • 2
    It would be helpful if you could show at what level of the `validate` object the `checkForm` method should be added. No one on any SO post is showing where to add the new method. – X_Trust Feb 13 '16 at 05:50
  • thanks it worked better . What is i need to remove validation on disabled fields – Vipin Singh Oct 03 '17 at 12:04
  • This is a very good solution. But if you don't want to change checkForm anouther solution is to use the addmethod and provide it in the class input attribute. Example: $.validator.addMethod("productlabel", function(value, element) {//do validation here}); Then: – George Plamenov Georgiev Mar 23 '18 at 13:12
  • 1
    @Amit Thank You. But Error message print only first row. – Chintan Jun 12 '18 at 04:55
  • You must be declare unique id for each input. If not, error message print only first element. – Trung Jun 16 '20 at 10:24
  • But this is not working for multiple file upload that is `` it is not working. I have written validation like `rules:{"gallery_images[]": { required: true }}` & `messages: {"gallery_images[]": { required: "Please upload images" } }` – Prasad Patel Jul 02 '20 at 06:09
  • 3
    Thanks..!! It is working.. One thing we have to Keep in Mind.. i.e `ID must be different for each Field` – Chandan Sharma Aug 08 '20 at 05:40
21

You can pass an option in to ignore part of a field name; As for the original posts comments, there are plenty of use-cases for having a name[] style name in HTML, especially using PHP.

$("#my-form").validate({
  submitHandler: function(form) {
    form.submit();
  },
  ignore: [],
  rules: {
    'category[]': {
      required: true
    }
  }
});
Sushant Pimple
  • 1,337
  • 1
  • 13
  • 26
Christo
  • 251
  • 2
  • 4
17

I noticed that the jQuery validate plugin i use will only detect the first element with a specific name.

Another way to make the jQuery validate plugin also detect all the inputs beyond the first could be by making the names unique. So you could replace:

<input type="text" name="qty[]" />
<input type="text" name="qty[]" />
<input type="text" name="qty[]" />
<input type="text" name="qty[]" />

with:

<input type="text" name="qty[0]" />
<input type="text" name="qty[1]" />
<input type="text" name="qty[2]" />
<input type="text" name="qty[3]" />
Quinten
  • 474
  • 4
  • 7
12

This is the Best solution I found and I'am currently using in my project:

// Adding rule to each item in qtyi list 
jQuery('[id^=qty]').each(function(e) {
    jQuery(this).rules('add', {
        minlength: 2,
        required: true
    });
});
Rafael Moni
  • 656
  • 1
  • 10
  • 22
Chris Sim
  • 4,054
  • 4
  • 29
  • 36
5

You need to make indexing of each elements

Below is html code.

<form id="transport-form">
  <input type="text" name="qty[0]" id="qty1">
  <input type="text" name="qty[1]" id="qty2" >
  <input type="text" name="qty[2]" id="qty3">
  <input type="text" name="qty[3]" id="qty4">
  <input type="submit value="submit">
</form>

and jquery code is below

jQuery("#transport-form").validate({
    rules: {
        'qty[]': {
            required: true
        }
    },
});
Ajay Patidar
  • 304
  • 3
  • 9
3

First, for jQuery to distinguish between the elements you need to have a different id per element. This can be done programmatically when you add the inputs. Then what you need to do is to verify all inputs with common name at once. For that, create a custom validator using the addMethod() function as described in the documentation

jQuery.validator.addMethod("allRequired", function(value, elem){
        // Use the name to get all the inputs and verify them
        var name = elem.name;
        return  $('input[name="'+name+'"]').map(function(i,obj){return $(obj).val();}).get().every(function(v){ return v; });
    });

You can use this as a rule on your array elements :

$('form').validate(
        {
         rules: { 
               "nbPieces[]": "allRequired"
         },

         submitHandler : function(form, event) {
              event.preventDefault();   
              //... etc
         }
});

For the errors to appear correctly on the empty fields though, you may need to override the errorPlacement option from validate...

Eva M
  • 625
  • 6
  • 11
1

Here the solution without giving indexing to array.

<form>
    <div>Name:
       <p>
        <input name="name_ct[]" id="id_ct0" type="text" class="form-control" placeholder="Add Variant 1 Name">
        </p>
    </div>
    <input type="button" value="Add Variant" />
    <input type="submit" />
</form>

js Code

$(document).ready(function () {
 $.validator.addMethod("mytst", function (value, element) {
        var flag = true;

      $("[name^=name_ct]").each(function (i, j) {
                        $(this).parent('p').find('label.error').remove();
$(this).parent('p').find('label.error').remove();                        
                        if ($.trim($(this).val()) == '') {
                            flag = false;

                            $(this).parent('p').append('<label  id="id_ct'+i+'-error" class="error">This field is required.</label>');
                        }
                    });


                    return flag;


    }, "");
$("form").validate({

    ignore: '',
    rules: {
        "name_ct[]": {
            mytst:true
        }
    },
    submitHandler: function () {
        //you can add code here to recombine the variants into one value if you like, before doing a $.post
         form.submit();
        alert('successful submit');
        return false;
    }
});

var j = 1;
$('input[type="button"]').click(function () {
    $('form div').append('<p><input name="name_ct[]" id="id_ct' + j + '" type="text" class="form-control" placeholder="Add Variant ' + j + ' Name " ></p>');

    j++;
});
});

you can see here in js fiddle: https://jsfiddle.net/q0d76aqx/42/

shankit
  • 11
  • 6
0

I've used solution proposed by AsgarAli Khanusiya but JQuery.Validator shows label with error message in same cases in the wrong place. It happens because it stores previously shown messages. If user make same mistake with different item in the collection then validator displays label in the previous place instead of generation new label near element with issue. I've overrided 'errorsFor' method to solve this:

$.validator.prototype.errorsFor = function (element) {
    var name = this.idOrName(element);
    var elementParent = element.parentElement;
    return this.errors().filter(function() {
        return $(this).attr('for') == name && $(this).parent().is(elementParent);
    });
}
Pavel
  • 1,015
  • 3
  • 13
  • 27
0
rules:{
     textname:{
     required:true
     },         
     'checkbox[]':{
      checkbox: true
   }
}

Please check this is very easy and working solution

Dhaval Darji
  • 513
  • 5
  • 19
Snuriya
  • 1
  • 1
0

Hi jQuery validation only validate 1st element of array input if you customize

checkForm: function() {
this.prepareForm();
for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) {
    if (this.findByName(elements[i].name).length != undefined && this.findByName(elements[i].name).length > 1) {
        for (var cnt = 0; cnt < this.findByName(elements[i].name).length; cnt++) {
            this.check(this.findByName(elements[i].name)[cnt]);
        }
    } else {
        this.check(elements[i]);
    }
}
return this.valid();} // this is not workig proper so you don't toch this code 

but I saw this code also not working some scenario so that i find Tigger point of form summation after validation. if you want to validate custom I share you trick you can customization you own validation then submit your form. code in below .

====================================================================

    checkForm: function() {
        this.prepareForm();
        for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
            this.check( elements[ i ] );
        }
        return this.valid();
    }, // write  as it is its woking now 

====================================================================

$(document).ready(function($) {

$("#my_form").validate({

rules: {
    "product_name": "required",                    
    // "product_image[]": "required",                    
                  
//  password: {
//      required: true,
//      minlength: 6
//  },
//    city: "required",
//   gender: "required"
 
},
messages: {
    "product_name": "Please enter Product Name",
    // "product_image[]": "required",  
//  password: {
//      required: "Please provide a password",
//      minlength: "Your password must be at least 6 characters long"
//  },
//   city: "Please enter your city",
//   gender: "This field is required"
},
 errorPlacement: function(error, element) 
{
if ( element.is(":radio") ) 
{
    error.appendTo( element.parents('.form-group') );
}
else 
{ // This is the default behavior 
    error.insertAfter( element );
}
},
    submitHandler: function(form) {
        var values = $("input[name='product_image[]']").map(function(){return $(this).val();}).get();
        for (let i = 0; i < values.length; i++) {
            if(values[i] === "")
            {
                
                alert('Please select Image on position : '+(i+1));
                return false;
            }else{

            }
        }
        console.log(values.includes(''));
        if(values.includes('') === false);
        {
            
            form.submit();

        }
    
    }
    
});

});

form.submit(); is main Tigger so you can write customize validation code before this run within submitHandler function scope I hope this solution is work for you

MOAZZAM RASOOL
  • 159
  • 1
  • 3
0

I'm trying to figure out what to do if input the name array has an index of a random token string.
It works fine without fixing the library.
It will avoid below error.

Uncaught TypeError: Cannot read properties of undefined (reading 'settings')

I found the solution:
Ex:
HTML

<form id="transport-form">
  <input type="text" name="qty[8Y8JoRtZtk]" id="qty_8Y8JoRtZtk" class="input-qty">
  <input type="text" name="qty[KpXdcWOEfK]" id="qty_KpXdcWOEfK" class="input-qty">
  <input type="text" name="qty[9cZtnHnq6J]" id="qty_9cZtnHnq6J" class="input-qty">
  <input type="text" name="qty[nCFzWUIcKW]" id="qty_nCFzWUIcKW" class="input-qty">
  <input type="submit value="submit">
</form>

JS:

setTimeout(function() {
   $('.input-qty').each(function(e) {
     $(this).rules('add', {
        required: true,
        number: true
     });
   })
}, 0);
tranthaihoang
  • 436
  • 1
  • 6
  • 22
-3

jQuery Form Validator is a feature rich and multilingual jQuery plugin that makes it easy to validate user input while keeping your HTML markup clean from javascript code. Even though this plugin has a wide range of validation functions it's designed to require as little jQuery network traffic as possible. This is achieved by grouping together validation functions in "modules", making it possible to load only those functions that's needed to validate a particular form.

<form action="" id="registration-form">
  <p>
    E-mail
    <input name="email" data-validation="email">
  </p>
  <p>
    User name
    <input name="user" data-validation="length alphanumeric" 
         data-validation-length="3-12" 
         data-validation-error-msg="User name has to be an alphanumeric value (3-12 chars)">
  </p>
  <p>
    Password
    <input name="pass_confirmation" data-validation="strength" 
         data-validation-strength="2">
  </p>
  <p>
    Repeat password
    <input name="pass" data-validation="confirmation">
  </p>
  <p>
    Birth date
    <input name="birth" data-validation="birthdate" 
         data-validation-help="yyyy-mm-dd">
  </p>
  <p>
    Country
    <input name="country" id="country" data-validation="country">
  </p>
  <p>
    Profile image
    <input name="image" type="file" data-validation="mime size required" 
         data-validation-allowing="jpg, png" 
         data-validation-max-size="300kb" 
         data-validation-error-msg-required="No image selected">
  </p>
  <p>
    User Presentation (<span id="pres-max-length">100</span> characters left)
    <textarea name="presentation" id="presentation"></textarea>
  </p>
  <p>
    <input type="checkbox" data-validation="required" 
         data-validation-error-msg="You have to agree to our terms">
    I agree to the <a href="..." target="_blank">terms of service</a>
  </p>
  <p>
    <input type="submit" value="Validate">
    <input type="reset" value="Reset form">
  </p>
</form>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-form-validator/2.3.26/jquery.form-validator.min.js"></script>
<script>

  $.validate({
    modules : 'location, date, security, file',
    onModulesLoaded : function() {
      $('#country').suggestCountry();
    }
  });

  // Restrict presentation length
  $('#presentation').restrictLength( $('#pres-max-length') );

</script>
...
O'Neil
  • 3,790
  • 4
  • 16
  • 30
  • 1
    Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its long-term value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Toby Speight Nov 17 '17 at 12:51