jQuery Validate – требует, по крайней мере, одного поля в заполняемой группе

Я использую отличный плагин jQuery Validate для проверки некоторых форм. В одной форме мне нужно убедиться, что пользователь заполняет хотя бы одну из группы полей. Я думаю, что у меня неплохое решение, и я хотел бы поделиться им. Просьба предложить любые улучшения, о которых вы можете подумать.

Не найдя встроенного способа сделать это, я обыскал и нашел обычную процедуру проверки Ребекки Мерфи , что было очень полезно.

Я улучшил это тремя способами:

  1. Чтобы позволить вам перейти в селектор для группы полей
  2. Чтобы указать, сколько из этой группы должно быть заполнено для проверки
  3. Чтобы показать все входы в группе как проверку прохождения, как только один из них пройдет проверку. (См. Крик к Ник Крейвер в конце.)

Таким образом, вы можете сказать: «По крайней мере, X-входы, соответствующие селектору Y, должны быть заполнены».

Конечный результат: с разметкой:

  

… это группа правил, таких как:

 // Both these inputs input will validate if // at least 1 input with class 'productinfo' is filled partnumber: { require_from_group: [1,".productinfo"] } description: { require_from_group: [1,".productinfo"] } 

В .checked № 3 предполагается, что при успешной проверке вы добавляете class сообщений .checked к сообщениям об ошибках. Вы можете сделать это следующим образом, как показано здесь .

 success: function(label) { label.html(" ").addClass("checked"); } 

Как и в приведенной выше демонстрации, я использую CSS, чтобы каждый span.error имел X-образ в качестве фона, если у него нет classа .checked , и в этом случае он получает изображение галочки.

Вот мой код:

 jQuery.validator.addMethod("require_from_group", function(value, element, options) { var numberRequired = options[0]; var selector = options[1]; //Look for our selector within the parent form var validOrNot = $(selector, element.form).filter(function() { // Each field is kept if it has a value return $(this).val(); // Set to true if there are enough, else to false }).length >= numberRequired; // The elegent part - this element needs to check the others that match the // selector, but we don't want to set off a feedback loop where each element // has to check each other element. It would be like: // Element 1: "I might be valid if you're valid. Are you?" // Element 2: "Let's see. I might be valid if YOU'RE valid. Are you?" // Element 1: "Let's see. I might be valid if YOU'RE valid. Are you?" // ...etc, until we get a "too much recursion" error. // // So instead we // 1) Flag all matching elements as 'currently being validated' // using jQuery's .data() // 2) Re-run validation on each of them. Since the others are now // flagged as being in the process, they will skip this section, // and therefore won't turn around and validate everything else // 3) Once that's done, we remove the 'currently being validated' flag // from all the elements if(!$(element).data('being_validated')) { var fields = $(selector, element.form); fields.data('being_validated', true); // .valid() means "validate using all applicable rules" (which // includes this one) fields.valid(); fields.data('being_validated', false); } return validOrNot; // {0} below is the 0th item in the options field }, jQuery.format("Please fill out at least {0} of these fields.")); 

Ура!

Выкрикивать

Теперь для этого крика – изначально мой код просто слепо скрывал сообщения об ошибках в других совпадающих полях вместо повторной проверки их, что означало, что если возникла другая проблема (например, «разрешены только номера и введены буквы») , он скрылся, пока пользователь не попытался подать. Это произошло потому, что я не знал, как избежать цикла обратной связи, упомянутого в комментариях выше. Я знал, что должен быть способ, поэтому я задал вопрос , и Ник Крейвер просветил меня. Спасибо, Ник!

Вопрос решен

Первоначально это было «позвольте мне рассказать об этом и посмотреть, может ли кто-нибудь предложить предложения». Хотя я все равно приветствую отзывы, я думаю, что на данный момент это довольно полно. (Это может быть короче, но я хочу, чтобы это было легко читать, а не обязательно лаконично.) Так просто наслаждайтесь!

Обновление – теперь часть проверки jQuery

Это было официально добавлено в jQuery Validation 4/3/2012.

Это отличное решение Натана. Большое спасибо.

Вот способ, которым работает вышеприведенный код, на случай, если кто-то столкнется с трудностями с его интеграцией, как и я:

Код внутри файла Additional-methods.js :

 jQuery.validator.addMethod("require_from_group", function(value, element, options) { ...// Nathan's code without any changes }, jQuery.format("Please fill out at least {0} of these fields.")); // "filone" is the class we will use for the input elements at this example jQuery.validator.addClassRules("fillone", { require_from_group: [1,".fillone"] }); 

Код внутри файла html :

     

Не забудьте добавить файл extra-methods.js!

Хорошее решение. Однако у меня была проблема с другими необходимыми правилами, которые не работают. Выполнение .valid () в отношении формы исправило эту проблему для меня.

 if(!$(element).data('being_validated')) { var fields = $(selector, element.form); fields.data('being_validated', true); $(element.form).valid(); fields.data('being_validated', false); } 

Спасибо, Шон. Это фиксировало проблему, с которой я столкнулся с кодом, игнорирующим другие правила.

Я также сделал несколько изменений, чтобы сообщение «Просьба заполнить хотя бы 1 поле» появилось в отдельном div, а не после каждого поля.

вставить скрипт проверки подлинности

 showErrors: function(errorMap, errorList){ $("#form_error").html("Please fill out at least 1 field before submitting."); this.defaultShowErrors(); }, 

добавьте это где-нибудь на страницу

 

добавить в метод require_from_group метод addMethod

  if(validOrNot){ $("#form_error").hide(); }else{ $("#form_error").show(); } ...... }, jQuery.format("  (!)")); 

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

Пример: http://jsfiddle.net/f887W/10/

 jQuery.validator.addMethod("require_from_group", function (value, element, options) { var validator = this; var minRequired = options[0]; var selector = options[1]; var validOrNot = jQuery(selector, element.form).filter(function () { return validator.elementValue(this); }).length >= minRequired; // remove all events in namespace require_from_group jQuery(selector, element.form).off('.require_from_group'); //add the required events to trigger revalidation if setting is enabled in the validator if (this.settings.onkeyup) { jQuery(selector, element.form).on({ 'keyup.require_from_group': function (e) { jQuery(selector, element.form).valid(); } }); } if (this.settings.onfocusin) { jQuery(selector, element.form).on({ 'focusin.require_from_group': function (e) { jQuery(selector, element.form).valid(); } }); } if (this.settings.click) { jQuery(selector, element.form).on({ 'click.require_from_group': function (e) { jQuery(selector, element.form).valid(); } }); } if (this.settings.onfocusout) { jQuery(selector, element.form).on({ 'focusout.require_from_group': function (e) { jQuery(selector, element.form).valid(); } }); } return validOrNot; }, jQuery.format("Please fill at least {0} of these fields.")); 

Запуск имени переменной с $ требуется в PHP, но довольно странно (IMHO) в Javascript. Кроме того, я считаю, что вы ссылаетесь на него как «$ module» дважды и «module» один раз, правильно? Кажется, что этот код не должен работать.

Кроме того, я не уверен, что это обычный синтаксис плагина jQuery, но я могу добавить комментарии над вашим вызовом addMethod, объясняя, что вы делаете. Даже с вашим текстовым описанием выше, это трудно выполнить код, потому что я не знаком с тем, что касается fieldset:: fill, value, element или selector. Возможно, большая часть этого очевидна для кого-то, кто знаком с плагином Validate, поэтому используйте суждение о том, какова правильная сумма объяснений.

Возможно, вы могли бы вырвать несколько варов для самодокументации кода; как,

 var atLeastOneFilled = module.find(...).length > 0; if (atLeastOneFilled) { var stillMarkedWithErrors = module.find(...).next(...).not(...); stillMarkedWithErrors.text("").addClass(...) 

(предполагая, что я понял смысл этих кусков вашего кода! :))

Я не совсем уверен, что означает «модуль», на самом деле – есть ли более конкретное имя, которое вы могли бы дать этой переменной?

Хороший код, в общем!

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

 var commonParent = $(element).parents(options[2]); 

и таким образом, селектор, идентификатор или имя элемента могут быть переданы один раз:

 jQuery.validator.addClassRules("reqgrp", {require_from_group: [1, ".reqgrp", 'fieldset']}); 

и валидатор ограничивает проверку элементов этим classом только внутри каждого набора полей, а не пытается подсчитать все classические элементы .reqgrp в форме.

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

 jQuery.validator.addMethod("require_from_group", function(value, element, options){ var numberRequired = options[0], selector = options[1], $fields = $(selector, element.form), validOrNot = $fields.filter(function() { return $(this).val(); }).length >= numberRequired, validator = this; if(!$(element).data('being_validated')) { $fields.data('being_validated', true).each(function(){ validator.valid(this); }).data('being_validated', false); } if (validOrNot) { $(selector).each(function() { $(this).removeClass('error'); $('label.error[for='+$(this).attr('id')+']').remove(); }); } return validOrNot; }, jQuery.format("Please fill out at least {0} of these fields.")); 

Единственная оставшаяся проблема с этим сейчас – это краевой случай, когда поле пусто, затем заполнено, а затем снова пуст … в этом случае ошибка будет применяться к одному полю, а не к группе. Но это кажется настолько маловероятным с любой частотой, и оно по-прежнему технически работает в этом случае.

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

 fields.valid(); 

К этому:

 var validator = this; fields.each(function(){ validator.valid(this); }); 

Я также сделал несколько (личных) улучшений, и это версия, которую я использую:

 jQuery.validator.addMethod("require_from_group", function(value, element, options){ var numberRequired = options[0], selector = options[1], $fields = $(selector, element.form), validOrNot = $fields.filter(function() { return $(this).val(); }).length >= numberRequired, validator = this; if(!$(element).data('being_validated')) { $fields.data('being_validated', true).each(function(){ validator.valid(this); }).data('being_validated', false); } return validOrNot; }, jQuery.format("Please fill out at least {0} of these fields.")); 

Спасибо, Натан. Ты спас мне много времени.

Однако я должен заметить, что это правило не является jQuery.noConflict () готово. Итак, нужно заменить все $ на jQuery для работы, скажем, var $j = jQuery.noConflict()

И у меня вопрос: как я могу заставить его вести себя как встроенное правило? Например, если я вхожу в адрес электронной почты, сообщение «Пожалуйста, введите действительный адрес электронной почты» автоматически исчезнет, ​​но если я заполнил одно из сообщений об ошибках группового поля.

  • jQuery validator и настраиваемое правило, использующее AJAX
  • Пользовательский формат даты с плагином проверки jQuery
  • (Встроенный) способ в JavaScript, чтобы проверить, является ли строка допустимым числом
  • Как проверить файл XML с помощью Java с XSD с включенным?
  • Уникальное ограничение с JPA и проверкой Bean
  • Как проверить, является ли файл Unix .tar.gz действительным файлом без разжатия?
  • Как заставить валидацию зависеть от нажатой кнопки?
  • Как пометить вход ячейки JTable как недействительный?
  • JSF skip Required-Validation без немедленного = true
  • Проверка файла XML на локальный DTD-файл с помощью Java
  • как я могу проверить ввод пользователя как двойной в C ++?
  • Давайте будем гением компьютера.