Estou usando o excelente jQuery Validate Plugin para validar alguns formulários. Em um formulário, preciso garantir que o usuário preencha pelo menos um de um grupo de campos. Acho que tenho uma solução muito boa e gostaria de compartilhá-la. Por favor, sugira quaisquer melhorias que você possa imaginar.
Não encontrando uma maneira integrada de fazer isso, pesquisei e encontrei o método de validação personalizado de Rebecca Murphey , que foi muito útil.
Eu melhorei isso de três maneiras:
- Para permitir que você passe um seletor para o grupo de campos
- Para permitir que você especifique quantos desse grupo devem ser preenchidos para a validação passar
- Para mostrar todas as entradas no grupo como aprovadas na validação assim que uma delas passar na validação. (Veja a mensagem para Nick Craver no final.)
Portanto, você pode dizer "pelo menos X entradas que correspondem ao seletor Y devem ser preenchidas."
O resultado final, com marcação como esta:
<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">
... é um grupo de regras como este:
// 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"]
}
O item nº 3 assume que você está adicionando uma classe de .checked
às suas mensagens de erro após a validação bem-sucedida. Você pode fazer isso da seguinte maneira, conforme demonstrado aqui .
success: function(label) {
label.html(" ").addClass("checked");
}
Como na demonstração vinculada acima, eu uso CSS para dar a cada span.error
um uma imagem X como plano de fundo, a menos que ele tenha a classe .checked
, caso em que recebe uma imagem de marca de seleção.
Este é meu código até agora:
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."));
Hooray!
Gritar
Agora, para essa mensagem - originalmente, meu código apenas ocultou cegamente as mensagens de erro nos outros campos correspondentes em vez de revalidá-los, o que significava que se houvesse outro problema (como 'apenas números são permitidos e você inseriu letras') , ficou oculto até que o usuário tentou enviar. Isso porque eu não sabia como evitar o ciclo de feedback mencionado nos comentários acima. Eu sabia que devia haver um caminho, então fiz uma pergunta e Nick Craver me esclareceu. Obrigado, Nick!
Questão Resolvida
Originalmente, esse era um tipo de pergunta "deixe-me compartilhar isso e ver se alguém pode sugerir melhorias". Embora eu ainda receba feedback, acho que está bem completo neste ponto. (Pode ser mais curto, mas quero que seja fácil de ler e não necessariamente conciso.) Então, divirta-se!
Atualização - agora parte da validação jQuery
Isso foi adicionado oficialmente à validação do jQuery em 03/04/2012.