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

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

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

Спасибо за Ваше внимание.

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

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

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

Более элегантное решение было опубликовано здесь: 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(); } 

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

Вместо изменения исходного файла 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(); }; 

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

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

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

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

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

 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[]"]'); 

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

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

 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 ). Затем я перемещаю все дочерние элементы дочерних элементов на свою вкладку и проверяю их на достоверность.

Все остальное является стандартным.


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

  

И здесь функция 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 } } }); 

Я использую «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; }); }; } 

});

Возможно, мне не хватает смысла, но поскольку валидатор не работает с несколькими именами (попробовал … не удалось!) Я изменил свою форму, чтобы динамически изменять имена, устанавливать правила, а затем отменить имена в 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--", 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); } }); } } 

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

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

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

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

 revertGeneratedNames(form, ['amounts']); 

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

Я думаю, вы неправильно поняли работу 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 или адаптировать его, если вы написали его самостоятельно.

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

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

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

 $(document).ready(function() { $(".form").each(function() { $(this).validate({ ... ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form. ... }); }); }); 
  • ASP.NET MVC Отключить проверку на стороне клиента на уровне поля
  • Как заставить валидацию зависеть от нажатой кнопки?
  • Остановить форму отправки, используя JQuery
  • Как использовать Scanner для принятия только действительного int в качестве входного
  • как я могу проверить ввод пользователя как двойной в C ++?
  • Есть ли разница между «действительным xml» и «хорошо сформированным xml»?
  • Regexp распознавание адреса электронной почты трудно?
  • C # WinForms ErrorProvider Control
  • Плагин jQuery Validation в веб-формах ASP.NET
  • Как использовать IDataErrorInfo.Error в программе WPF?
  • Подтвердите JSON против JSON Schema C #
  • Давайте будем гением компьютера.