Using jQuery Validate Plugin to validate multiple form fields with the same name

I have a dynamically generated form with input fields with the same name (for example: "map"). I have no way to change field names or generate unique field names, because the code of the form handler (Perl / CGI) is designed to process an array of input values ​​(in this case @map ).

How can I use jQuery Validated Plugin to validate form in this situation? In particular, I would like for exactly one element of the represented array to have a certain fixed value. I am currently using a special event handler that creates a JSON object with serializeArray() and then passes it to make sure the condition is met. But since I used the Validate plugin in the rest of the application, I was wondering if such a case could be handled using the same plugin here.

Thank you for your attention.

+44
jquery jquery-validate validation
May 31 '09 at 9:03
source share
12 answers

I spent some time searching and trying different things when, finally, I tried the most trivial way to do a check on several fields. Each field and its clones share a class unique to each set. I just looped over the inputs with this class and added my validation rules as usual. Hope this helps someone else.

  $("#submit").click(function(){ $("input.years").each(function(){ $(this).rules("add", { required: true, messages: { required: "Specify the years you worked" } } ); }); $("input.employerName").each(function(){ $(this).rules("add", { required: true, messages: { required: "Specify the employer name" } } ); }); $("input.employerPhone").each(function(){ $(this).rules("add", { required: true, minlength: 10, messages: { required: "Specify the employer phone number", minlength: "Not long enough" } } ); }); $("input.position").each(function(){ $(this).rules("add", { required: true, messages: { required: "Specify your position" } } ); }); $("input.referenceName").each(function(){ $(this).rules("add", { required: true, messages: { required: "Specify the reference name" } } ); }); $("input.referencePhone").each(function(){ $(this).rules("add", { required: true, minlength: 10, messages: { required: "Specify your reference phone number", minlength: "Not long enough" } } ); }); // Now do your normal validation here, but don't assign rules/messages for the fields we just set them for }); 
+37
Aug 6 '09 at 2:12
source share

An old thread that I know, but I came across it in search of a fix to the same problem.

Here's a more elegant solution: http://web-funda.blogspot.com/2009/05/jquery-validation-for-array-of-input.html

You just edit jquery.validate.js and change checkForm to

  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(); } 
+53
Nov 09 '10 at 17:11
source share

As I cannot comment on @scampbell's answer, I don’t know if its about reputation points or because the stream has just been closed, I have a contribution to its answer.

Instead of modifying the original jquery.validation file, you can simply override the function that needs to be edited only on the required pages.

example:

 $.validator.prototype.checkForm = function() { //overriden in a specific page 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 may not be the best solution, but at least it avoids editing the source files, which can be replaced later when a new version is released. where your overriden function may or may not break

+51
Jul 31 '12 at 12:55
source share

I just found out from a letter by plugin author JΓΆrn Zaefferer that to check the validity of field names are unique, with the exception of radio buttons and checkboxes.

+10
Jun 01 '09 at 4:47
source share

Jason's answer will do the trick, but I did not want to add additional click events to each form on which I did it.

In my case, I have a validation plugin that considers names ending in "[]" different, even if they can have the same field names. To do this, I overwrote these two internal methods after loading jquery.validate.js.

 $.validator.prototype.elements= function() { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved return $([]).add(this.currentForm.elements) .filter(":input") .not(":submit, :reset, :image, [disabled]") .not( this.settings.ignore ) .filter(function() { !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); // select only the first element for each name (EXCEPT elements that end in []), and only those with rules specified if ( (!this.name.match(/\[\]/gi) && this.name in rulesCache) || !validator.objectLength($(this).rules()) ) return false; rulesCache[this.name] = true; return true; }); }; $.validator.prototype.idOrName = function(element) { // Special edit to get fields that end with [], since there are several [] we want to disambiguate them // Make an id on the fly if the element doesnt have one if(element.name.match(/\[\]/gi)) { if(element.id){ return element.id; } else { var unique_id = new Date().getTime(); element.id = new Date().getTime(); return element.id; } } return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); }; 
+4
Mar 31 2018-11-11T00:
source share

Just use an unused input attribute to keep the original name, and then just rename it with the index attached:

 function addMultiInputNamingRules(form, field, rules){ $(form).find(field).each(function(index){ $(this).attr('alt', $(this).attr('name')); $(this).attr('name', $(this).attr('name')+'-'+index); $(this).rules('add', rules); }); 

}

 function removeMultiInputNamingRules(form, field){ $(form).find(field).each(function(index){ $(this).attr('name', $(this).attr('alt')); $(this).removeAttr('alt'); }); 

}

Then after you install the validator:

 addMultiInputNamingRules('#form-id', 'input[name="multifield[]"]', { required:true }); 

and when you finish checking, go back like this:

 removeMultiInputNamingRules('#form-id', 'input[alt="multifield[]"]'); 

- Hope this helps!

+3
Oct 19 '10 at 20:05
source share

Here is how I did it. A little easier than the previously proposed methods:

 function validateTab(tab) { var valid = true; $(tab).find('input').each(function (index, elem) { var isElemValid = $("#registrationForm").validate().element(elem); if (isElemValid != null) { //this covers elements that have no validation rule valid = valid & isElemValid; } }); return valid; } 

In my case, I have a wizard (of 3 steps), which turned out to be even more complicated, because I do not want to check all the fields at once. I mainly place components in tabs, and if the first tab is valid, I go to the next until I get the last, and then send all the data. So the tab parameter is the actual tab element (which is the div ). Then I iterate over all the children of the children in my tab and check their validity.

Everything else is standard.




Just for completeness, the rest of the code is here: how the form is submitted and what my validator looks like:

 <a href="javascript:moveToNextTab(1)" class="button next">Submit</a> 

And here the js function is called:

 function moveToNextTab(currentTab) { var tabs = document.getElementsByClassName("tab"); //loop through tabs and validate the current one. //If valid, hide current tab and make next one visible. } 

I use these validation rules (which I create on jQuery.ready):

 $("#registrationForm").validate({ rules: { birthdate: { required: true, date: true }, name: "required", surname: "required", address: "required", postalCode: "required", city: "required", country: "required", email: { required: true, email: true } } }); 
+3
Jan 17 '12 at 16:12
source share

I am using the "jQuery validation plug-in 1.7".

The problem is why multiple $ (: input) elements that have the same name are not checked

- $ .validator.element method:

 elements: function() { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved return $([]).add(this.currentForm.elements) .filter(":input") .not(":submit, :reset, :image, [disabled]") .not( this.settings.ignore ) .filter(function() { !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); // select only the first element for each name, and only those with rules specified if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) return false; rulesCache[this.name] = true; return true; }); }, 

Condition

if (this.name in rulesCache || .....

estimates that the second and next elements have the same name true ....

The solution will have the condition:

(this.id || this.name) in rulesCache

Sorry, JS puritans, that (this.id || this.name) is not 100% ...

Sure,

rulesCache [this.name] = true;

Line

must also be amended accordingly.

So the $ .validator.prototype.elements method will be:

 $(function () { if ($.validator) { //fix: when several input elements shares the same name, but has different id-ies.... $.validator.prototype.elements = function () { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved return $([]).add(this.currentForm.elements) .filter(":input") .not(":submit, :reset, :image, [disabled]") .not(this.settings.ignore) .filter(function () { var elementIdentification = this.id || this.name; !elementIdentification && validator.settings.debug && window.console && console.error("%o has no id nor name assigned", this); // select only the first element for each name, and only those with rules specified if (elementIdentification in rulesCache || !validator.objectLength($(this).rules())) return false; rulesCache[elementIdentification] = true; return true; }); }; } 

});

+2
Jun 28 '11 at 19:29
source share

I may be missing a point, but since the validator does not work with multiple names (I tried ... failed!) I changed my form to dynamically change names, set rules, and then cancel the names in submit.

Two methods (ignore the wlog stuff, it just prints to the console):

 // convert the field names into generated ones to allow fields with the same names // to be validated individually. The original names are stored as data against the // elements, ready to be replaced. The name is replaced with // "multivalidate-<name>-<id>", eg original => 'multivalidate-original-1' function setGeneratedNamesWithValidationRules(form, fields, rules) { var length = fields.length; for (var i=0; i < length; ++i ){ var name = fields[i]; var idCounter = 0; // we match either the already converted generator names or the original $("form [name^='multivalidate-" + name + "'], form [name='" + name + "']").each(function() { // identify the real name, either from the stored value, or the actual name attribute var realName = $(this).data('realName'); if (realName == undefined) { realName = $(this).attr("name"); $(this).data('realName', realName); } wlog("Name: " + realName + " (actual: " + $(this).attr("name") + "), val: " + $(this).val() + ". Rules: " + rules[realName]); $(this).attr("name", "multivalidate-" + realName + "-" + idCounter); if (rules[realName]) { $(this).rules("add", rules[realName]); } idCounter++; }); } } function revertGeneratedNames(form, fields) { var length = fields.length; for (var i=0; i < length; ++i ){ var name = fields[i]; wlog("look for fields names [" + name + "]"); $("form [name^='multivalidate-" + name + "']").each(function() { var realName = $(this).data('realName'); if (realName == undefined) { wlog("Error: field named [" + $(this).attr("name") + "] does not have a stored real name"); } else { wlog("Convert [" + $(this).attr("name") + "] back to [" + realName + "]"); $(this).attr("name", realName); } }); } } 

When I load the form and whenever I dynamically add another line, I call the set method, for example.

 setGeneratedNamesWithValidationRules($("#my-dynamic-form"), ['amounts'], { 'amounts': 'required'} ); 

This changes the names to allow individual verification.

In submitHandler: thingumy after checking, I call revert, i.e.

 revertGeneratedNames(form, ['amounts']); 

Switch names to originals before sending data.

+1
Oct 19 2018-10-10
source share

I think you misunderstood the work of HTML forms. Each form element must have a unique name, except for several flags and buttons that allow you to select one or more parameters for one data field.

In your case, not only JQuery validation, but server-side authentication will fail as it cannot assign inputs to data fields. Suppose you want a user to enter a first name, last name, email address, fax (optional), and all your input fields have name="map"

Then you will get these lists in submit:

 map = ['Joe','Doe','joe.doeAThotmail.com','++22 20182238'] //All fields completed map = ['Joe','Doe','joe.doeAThotmail.com'] //OK, all mandatory fields completed map = ['Doe', 'joe.doeAThotmail.com','++22 20182238']//user forgot prename, should yield error 

You see that it is not possible to reliably confirm this form.

I recommend revising the documentation for your perl form handler or adapting it if you wrote it yourself.

0
Jun 02 '09 at 15:50
source share

For me it was solved very easily by turning off the debugging

  $("#_form").validate({ debug:false, //debug: true, ... }); 
0
Apr 05 '15 at 10:00
source share

There is a simple solution:

 $(document).ready(function() { $(".form").each(function() { $(this).validate({ ... ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form. ... }); }); }); 
-one
Sep 19 '11 at 7:15
source share



All Articles