views:

6518

answers:

6

I have a dynamically generated form with input fields with the same name (for example: "map"). I do not have the option of changing the field names or generating unique field names because the form handler code (Perl/CGI) is designed to handle an array of input values (in this case @map).

How can I use the JQuery Validate Plugin to validate a form in such a situation? Specifically I would want exactly one element of the submitted array to have a certain fixed value. I am currently using a custom event handler that creates a JSON object with serializeArray() and then traverses it to ensure that the condition is met. But since I have used the Validate Plugin in the rest of the application, I was wondering if such a case may be handled using the same plugin here too.

Thank you for your attention.

+3  A: 

I have just learnt from a mail by the Plugins author Jörn Zaefferer that validation requires field names to be unique except for radio buttons and checkboxes. The mail is here: Jorn's Mail

Gurunandan
+4  A: 

I think you misunderstood the workings of HTML forms. Every form element needs to have an unique name, except multiple checkboxes and buttons that allow you to choose one/multiple options for one data field.

In your case, not only JQuery validation, but also a server-side form validator would fail, because it can't assign the inputs to the data fields. Suppose, you want the user to enter prename, lastname, e-mail-adress, fax (optional) and all your input fields have name="map"

Then you would receive these lists on 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 impossible to validate this form reliably.

I recommend to revisit the documentation of your perl form handler or adapt it if you wrote it on your own.

Franz
While I broadly agree with you, that form variables should have distinct names, it is not a requirement of the HTML standard. Your example is right in its context - it would be silly to assign the same variable names to what are semantically distinct attributes. However in my case, I have a situation where I need to submit 4 values for what are semantically identical variables: Names of upto 4 children for example, where it makes perfect sense both semantically and standards-wise to give identical names and collect them into a server-side array. I trust you will reconsider your comment
Gurunandan
+9  A: 

I spent some time searching and trying different things when finally I tried the most trivial way of doing validation on multiple fields. Each field and it's clones share a class unique to each set. I just looped through the inputs with that class and added my validation rules as usual. I hope this might help 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





});
helped me a great deal
frictionlesspulley
A: 

i have tried the $(selector).each method which u have suggested, but when i submit the page with all empty fields error message is displayed only for the first input element...

is there any other alternate way to validate all the input elements with the same name??

Kiran Reddy
A: 

Maybe I'm missing the point, but since the validator doesn't work with multiple names (tried... failed!) I changed my form to dynamically change the names, set the rules, then unset the names on submit.

Two methods (ignore the wlog stuff, it just outputs 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>", e.g. 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);
            }
        });
    }
}

On the form load, and whenever I dynamically add another row, I call the set method, e.g.

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

This changes the names to allow individual validation.

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

revertGeneratedNames(form, ['amounts']);

Which switches the names back to the originals before posting the data.

Alfonzo
A: 

Simply use an unused attribute of the input to store the original name, then just rename with it's 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 set your validator:

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

and when you've finished validating, revert back like so:

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

-- Hope this helps!

Matt Kircher