En utilisant JQuery Valider Plugin pour valider plusieurs champs de formulaire avec des noms identiques

StackOverflow https://stackoverflow.com/questions/931687

Question

I ai un formulaire généré dynamiquement avec des champs d'entrée avec le même nom (par exemple: « map »). Je ne suis pas la possibilité de modifier les noms de champs ou de générer des noms de champ uniques parce que le code du gestionnaire de formulaire (Perl / CGI) est conçu pour gérer un tableau de valeurs d'entrée (dans ce cas de @map).

Comment puis-je utiliser le Valider Plugin pour valider un formulaire une telle situation? Plus précisément, je voudrais exactement un élément du tableau soumis à une certaine valeur fixe. J'utilise actuellement un gestionnaire d'événements personnalisé qui crée un objet JSON avec serializeArray() et traverse ensuite pour faire en sorte que la condition est remplie. Mais depuis que je l'ai utilisé le plugin Valider dans le reste de l'application, je me demandais si ce cas peut être traité en utilisant le même plug-in ici.

Je vous remercie de votre attention.

Était-ce utile?

La solution

J'ai passé quelque temps à chercher et à essayer différentes choses quand finalement j'ai essayé la manière la plus triviale de faire la validation sur plusieurs champs. Chaque champ et il est des clones partagent une classe unique à chaque ensemble. Je viens en boucle à travers les entrées avec cette classe et ajouté mes règles de validation, comme d'habitude. J'espère que cela pourrait aider quelqu'un d'autre.

    $("#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





});

Autres conseils

Comme je ne peux pas commenter @scampbell réponse, je ne sais pas si son sur les points de réputation ou parce que le fil vient de fermer, j'ai une contribution à sa réponse,

Au lieu de modifier le fichier source jquery.validation vous pouvez simplement remplacer la fonction que vous devez modifier seulement dans les pages qui l'exige.

un exemple serait:

$.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();
};

cela pourrait ne pas être la meilleure solution, mais au moins il évite les fichiers source d'édition qui pourrait être remplacée plus tard, quand une nouvelles versions. où votre fonction surchargée peut ou ne pas casser

Vieux fil Je sais, mais je suis tombé dans la recherche de la solution au même problème.

Une solution plus élégante a été affichée ici: http: //web-funda.blogspot .com / 2009/05 / jquery-validation-for-gamme-de-input.html

Il vous suffit de modifier jquery.validate.js et changer le checkForm à

    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();
}

Je viens d'apprendre d'un courrier par l'auteur Plugins, Jörn Zaefferer, que la validation nécessite des noms de champ être unique à l'exception des boutons radio et cases à cocher.

La réponse de Jason fera l'affaire, mais je ne voulais pas ajouter des événements click sur toutes les formes que je l'ai fait sur.

Dans mon cas, je le plugin de validation considèrent les noms qui se terminent par « [] » différentes, même si elles peuvent avoir fieldnames identiques. Pour ce faire, je réenregistrés ces deux méthodes internes après jquery.validate.js charges.

$.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);
};

Il suffit d'utiliser un attribut inutilisé de l'entrée pour enregistrer le nom d'origine, puis il suffit de renommer avec son index ci-joint:

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');
});

}

Ensuite, après avoir défini votre validateur:

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

et quand vous avez terminé la validation, revenir comme ceci:

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

- Espérons que cela aide!

Voici comment je l'ai fait. Un peu plus facile que les méthodes proposées précédemment:

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;
}

Dans mon cas, j'ai un assistant (3 étapes) qui se révèle être encore plus complexe que je ne veux pas valider tous les champs à la fois. Je place essentiellement des composants dans des onglets et si le premier onglet est valide, je propose à l'autre, jusqu'à ce que je durer un, après que je soumets toutes les données. Ainsi, le paramètre de tab il y a l'élément de patte réelle (qui est un div). Je boucle puis à travers tous les éléments d'entrée des enfants à mon onglet et vérifier leur validité.

Tout le reste est standard.


Juste pour être complet est ici le reste du code: comment le formulaire soumettons est fait et comment mon validateur ressemble à:

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

Et ici la fonction js appelé:

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.
}

J'utilise ces règles de validation (que je crée sur 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
        }
    }
});

J'utilise "plug-in validation jQuery 1.7".

Le problème pourquoi plusieurs « $ (entrée:) » éléments partageant le même nom ne sont pas validées

est la méthode de .validator.element $:

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;
        });
    },

La condition

if (this.name dans rulesCache || .....

pour évaluer les éléments et les suivants qui partagent le même nom vrai ....

La solution serait d'avoir la condition:

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

Excusez-moi, JS puritains, que (this.id || this.name) n'est pas à 100% ...

Bien sûr, le

rulesCache [this.name] = true;

La ligne doit être modifiée de façon appropriée ainsi.

Ainsi, la méthode .validator.prototype.elements $ serait:

$(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;
        });
    };
}

});

Peut-être que je manque le point mais puisque le validateur ne fonctionne pas avec plusieurs noms (essayé ... a échoué!) J'ai changé ma forme pour modifier dynamiquement les noms, définissez les règles, les noms unset soumettre .

Deux méthodes (ne pas tenir les choses wlog, il produit juste à la 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);
            }
        });
    }
}

de la charge de la forme, et chaque fois ajouter dynamiquement une autre rangée, la parole est la méthode définie, par exemple.

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

Cela change les noms pour permettre la validation individuelle.

Dans le submitHandler. Thingumy après validation j'appelle le Revert, i.e.

revertGeneratedNames(form, ['amounts']);

qui commute les noms Retour aux originaux avant de poster les données.

Je pense que vous avez mal compris le fonctionnement des formulaires HTML. Chaque élément de formulaire doit avoir un nom unique, à l'exception de plusieurs cases à cocher et des boutons qui vous permettent de choisir un / plusieurs options pour un champ de données.

Dans votre cas, non seulement la validation JQuery, mais aussi une forme côté serveur validateur échouerait, car il ne peut pas affecter les entrées aux champs de données. Supposons que vous voulez que l'utilisateur d'entrer PRFNOM, nom, adresse e-mail, fax (en option) et tous les champs de saisie ont name="map"

Ensuite, vous recevrez ces listes sur soumettre:

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

Vous voyez qu'il est impossible de valider cette forme fiable.

Je recommande de revoir la documentation de votre gestionnaire de formulaire perl ou de l'adapter si vous avez écrit sur votre propre.

Pour moi, cela a été résolu très facilement en désactivant le débogage

 $("#_form").validate({
    debug:false,
    //debug: true,
    ...
    });

Il existe une solution simple:

$(document).ready(function() {
   $(".form").each(function() {
      $(this).validate({
         ...
         ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form.
         ...
      });
   });
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top