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.
fuente
Respuestas:
Esa es una excelente solución Nathan. Muchas gracias.
Aquí hay una forma de hacer que el código anterior funcione, en caso de que alguien tenga problemas para integrarlo, como hice yo:
Código dentro del archivo additional-methods.js :
Código dentro del archivo html :
¡No olvide incluir el archivo additional-methods.js!
fuente
require_from_group: [1,".partnumber"]
y...[1,".contactname"]
asegurarse de que está validando las cosas correctas.Buena solucion. Sin embargo, tuve el problema de que otras reglas requeridas no funcionaban. La ejecución de .valid () contra el formulario solucionó este problema.
fuente
validator.formSubmit = true
. En el método require-from-group, luego verifico esa bandera; si está ahí lo hago$(element.form).valid();
, de lo contrario lo hagofields.valid();
.Gracias sean. Eso solucionó el problema que tuve con el código ignorando otras reglas.
También hice algunos cambios para que el mensaje 'Por favor complete al menos 1 campo ...' se muestre en un div separado en lugar de después de todos los campos.
poner en forma validar script
agregue esto en algún lugar de la página
agregar al método require_from_group función addMethod
fuente
Envié un parche que no sufre los problemas de la versión actual (por lo que la opción "requerida" deja de funcionar correctamente en otros campos, una discusión sobre los problemas con la versión actual está en github .
Ejemplo en http://jsfiddle.net/f887W/10/
fuente
En PHP se requiere comenzar un nombre de variable con $, pero bastante extraño (en mi humilde opinión) en Javascript. Además, creo que se refiere a él como "$ módulo" dos veces y "módulo" una vez, ¿verdad? Parece que este código no debería funcionar.
Además, no estoy seguro de si es la sintaxis normal del complemento jQuery, pero podría agregar comentarios sobre su llamada addMethod, explicando lo que logra. Incluso con la descripción de texto anterior, es difícil seguir el código, porque no estoy familiarizado con el conjunto de campos,: relleno, valor, elemento o selector al que se refieren. Quizás la mayor parte de esto sea obvio para alguien familiarizado con el complemento Validate, así que use su juicio sobre cuál es la cantidad correcta de explicación.
Quizás podría romper algunas vars para autodocumentar el código; me gusta,
(¡asumiendo que entendí el significado de estos fragmentos de su código! :))
No estoy exactamente seguro de lo que significa "módulo", en realidad, ¿hay un nombre más específico que pueda darle a esta variable?
Buen código, en general!
fuente
Debido a que el formulario en el que estoy trabajando tiene varias regiones clonadas con entradas agrupadas como estas, pasé un argumento adicional al constructor require_from_group, cambiando exactamente una línea de su función addMethod:
y de esta manera un selector, ID o nombre de elemento se puede pasar una vez:
y el validador restringirá la validación a elementos con esa clase solo dentro de cada conjunto de campos, en lugar de intentar contar todos los elementos clasificados .reqgrp en el formulario.
fuente
Aquí está mi respuesta a la respuesta de Rocket Hazmat, tratando de resolver el problema de otros campos definidos que también necesitan ser validados, pero marcando todos los campos como válidos en el llenado exitoso de uno.
El único problema que queda con esto ahora es el caso límite en el que el campo está vacío, luego se llena, luego se vacía nuevamente ... en cuyo caso el error se aplicará al campo único, no al grupo. Pero eso parece muy poco probable que suceda con alguna frecuencia y todavía funciona técnicamente en ese caso.
fuente
Tenía problemas con otras reglas que no se verificaban junto con esto, así que cambié:
A esto:
También hice algunas mejoras (personales), y esta es la versión que estoy usando:
fuente
Gracias, Nathan. Me ahorraste un montón de tiempo.
Sin embargo, debo notar que esta regla no está lista para jQuery.noConflict (). Entonces, uno debe reemplazar todos $ con jQuery para trabajar, digamos,
var $j = jQuery.noConflict()
Y tengo una pregunta: ¿cómo haría que se comportara como una regla incorporada? Por ejemplo, si ingreso un correo electrónico, el mensaje "Ingrese un correo electrónico válido" desaparece automáticamente, pero si completo uno de los campos del grupo, el mensaje de error permanece.
fuente