Подтвердить что ты не робот

Использование JQuery Validate Plugin для проверки нескольких полей формы с одинаковыми именами

У меня есть динамически сгенерированная форма с полями ввода с тем же именем (например: "map" ). У меня нет возможности изменять имена полей или генерировать уникальные имена полей, потому что код обработчика формы (Perl/CGI) предназначен для обработки массива входных значений (в данном случае @map).

Как я могу использовать JQuery Validated Plugin для проверки формы в такой ситуации? В частности, я хотел бы, чтобы ровно один элемент представленного массива имел определенное фиксированное значение. В настоящее время я использую специальный обработчик событий, который создает объект JSON с serializeArray(), а затем проходит его, чтобы убедиться, что условие выполнено. Но поскольку я использовал плагин Validate в остальной части приложения, мне было интересно, может ли такой случай обрабатываться с использованием того же плагина здесь.

Благодарим вас за внимание.

4b9b3361

Ответ 1

Я потратил некоторое время на поиск и пробую разные вещи, когда, наконец, я попробовал самый тривиальный способ сделать проверку на нескольких полях. Каждое поле и его клоны разделяют класс, уникальный для каждого набора. Я просто зациклился на входах с этим классом и добавил мои правила проверки, как обычно. Надеюсь, это поможет кому-то другому.

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





});

Ответ 2

Старый поток, который я знаю, но я наткнулся на него в поисках исправления к той же проблеме.

Здесь представлено более элегантное решение: http://web-funda.blogspot.com/2009/05/jquery-validation-for-array-of-input.html

Вы просто редактируете jquery.validate.js и меняете 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();
}

Ответ 3

Как я не могу прокомментировать ответ @scampbell, я не знаю, если его о точках репутации или потому, что поток только что закрыт, у меня есть вклад в его ответ,

Вместо изменения исходного файла jquery.validation вы можете просто переопределить функцию, которую нужно редактировать только на требуемых страницах.

пример:

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

это может быть не лучшее решение, но, по крайней мере, это позволяет избежать редактирования исходных файлов, которые могут быть заменены позже при выпуске новой версии. где ваша функция overriden может или не сломаться

Ответ 4

Я только что узнал из письма автора плагинов Jörn Zaefferer, что для проверки правильности имен полей являются уникальными, за исключением переключателей и флажков.

Ответ 5

Ответ Джейсона будет делать трюк, но я не хотел добавлять дополнительные события кликов в каждую форму, на которой я это делал.

В моем случае у меня есть плагин проверки, который рассматривает имена, заканчивающиеся на "[]" разные, даже если они могут иметь одинаковые имена полей. Для этого я перезаписал эти два внутренних метода после загрузки 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);
};

Ответ 6

Просто используйте неиспользуемый атрибут ввода для сохранения исходного имени, а затем просто переименуйте его с прикрепленным индексом:

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

}

Затем после того, как вы установите валидатор:

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

и когда вы закончите проверку, верните назад так:

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

- Надеюсь, это поможет!

Ответ 7

Вот как я это сделал. Немного проще, чем ранее предлагаемые методы:

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

В моем случае у меня есть мастер (из 3 шагов), который оказался еще более сложным, поскольку я не хочу проверять все поля одновременно. Я в основном размещаю компоненты в вкладках, и если первая вкладка действительна, я перехожу к следующему, пока не получу последний, после чего отправлю все данные. Таким образом, параметр tab есть фактический элемент табуляции (который является div). Затем я перебираю все дочерние элементы дочерних элементов в свою вкладку и проверяю их на достоверность.

Все остальное стандартно.


Просто для полноты здесь остальная часть кода: как выполняется подача формы и как выглядит мой валидатор:

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

И здесь функция js называется:

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

Я использую эти правила проверки (которые я создаю на 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
        }
    }
});

Ответ 8

Я использую "jQuery validation plug-in 1.7".

Проблема, почему несколько элементов "$ (: input)", имеющих одно и то же имя, не проверяются

- метод $.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;
        });
    },

Условие

if (this.name в rulesCache ||.....

оценивает, что второй и следующий элементы имеют одно и то же имя true....

Решение будет иметь условие:

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

Извините, JS puritans, что (this.id || this.name) не на 100%...

Конечно,

rulesCache [this.name] = true;

Строка

также должна быть соответствующим образом изменена.

Таким образом, метод $.validator.prototype.elements будет:

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

});

Ответ 9

Возможно, мне не хватает точки, но поскольку валидатор не работает с несколькими именами (попробовал... не удалось!) Я изменил свою форму, чтобы динамически изменять имена, устанавливать правила, а затем отменить имена в submit.

Два метода (игнорируйте материал wlog, он просто выводится на консоль):

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

При загрузке формы и всякий раз, когда я динамически добавляю другую строку, я вызываю метод set, например.

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

Это изменяет имена, чтобы разрешить индивидуальную проверку.

В submitHandler: thingumy после проверки я вызываю revert, т.е.

revertGeneratedNames(form, ['amounts']);

Переключение имен на оригиналы перед отправкой данных.

Ответ 10

Я думаю, вы неправильно поняли работу HTML-форм. Каждый элемент формы должен иметь уникальное имя, кроме нескольких флажков и кнопок, которые позволяют вам выбрать один или несколько параметров для одного поля данных.

В вашем случае не только проверка JQuery, но и проверка подлинности на стороне сервера будет сбой, поскольку он не может назначить входы для полей данных. Предположим, вы хотите, чтобы пользователь вводил имя, фамилию, адрес электронной почты, факс (необязательно), и все ваши поля ввода имеют name="map"

Затем вы получите эти списки в 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

Вы видите, что невозможно достоверно подтвердить эту форму.

Я рекомендую пересмотреть документацию своего обработчика формы perl или приспособить его, если вы написали его самостоятельно.

Ответ 11

Для меня это было решено очень легко, отключив отладочную

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

Ответ 12

Существует простое решение:

$(document).ready(function() {
   $(".form").each(function() {
      $(this).validate({
         ...
         ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form.
         ...
      });
   });
});