Estoy usando el excelente complemento jQuery Validate para validar algunos formularios. En un formulario, necesito asegurarme de que el usuario complete al menos uno de un grupo de campos. Creo que tengo una solución bastante buena y quería compartirla. Sugiera cualquier mejora que se le ocurra.
Al no encontrar una forma incorporada de hacer esto, busqué y encontré el método de validación personalizado de Rebecca Murphey , que fue muy útil.
Mejoré esto de tres maneras:
- Para permitirle pasar un selector para el grupo de campos
- Para permitirle especificar cuántos de ese grupo se deben completar para que la validación pase
- Para mostrar todas las entradas del grupo como validación aprobada tan pronto como una de ellas pasa la validación. (Ver agradecimiento a Nick Craver al final).
Por lo tanto, puede decir "se deben completar al menos X entradas que coincidan con el selector Y".
El resultado final, con un marcado como este:
<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">
... es un grupo de reglas 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"]
}
El elemento n. ° 3 asume que está agregando una clase de .checked
a sus mensajes de error después de una validación exitosa. Puede hacer esto de la siguiente manera, como se demuestra aquí .
success: function(label) {
label.html(" ").addClass("checked");
}
Como en la demostración vinculada anteriormente, uso CSS para dar a cada uno span.error
una imagen X como fondo, a menos que tenga la clase .checked
, en cuyo caso obtiene una imagen de marca de verificación.
Aquí está mi código hasta ahora:
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."));
¡Hurra!
Gritar
Ahora, para ese saludo: originalmente, mi código simplemente ocultaba ciegamente los mensajes de error en los otros campos coincidentes en lugar de volver a validarlos, lo que significaba que si había otro problema (como 'solo se permiten números e ingresó letras') , se ocultó hasta que el usuario intentó enviarlo. Esto se debió a que no sabía cómo evitar el ciclo de retroalimentación mencionado en los comentarios anteriores. Sabía que debía haber una forma, así que hice una pregunta y Nick Craver me iluminó. ¡Gracias, Nick!
Pregunta resuelta
Esta fue originalmente una pregunta del tipo "déjame compartir esto y ver si alguien puede sugerir mejoras". Si bien aún agradecería comentarios, creo que en este momento está bastante completo. (Podría ser más corto, pero quiero que sea fácil de leer y no necesariamente conciso). ¡Así que disfrútalo!
Actualización: ahora parte de la validación de jQuery
Esto se agregó oficialmente a jQuery Validation el 4/3/2012.