¿Cómo usar Twitter Bootstrap popovers para jQuery notificaciones de validación?

Puedo hacer que los popovers aparezcan usando bootstrap con la suficiente facilidad, y también puedo hacer validaciones usando el plugin jQuery de validación estándar o el motor de validación jQuery , pero no puedo descifrar cómo alimentar uno con el otro.

Creo que lo que necesito es un gancho que el validador llama cuando quiere mostrar una notificación, darle un cierre que pase el mensaje y el elemento objective a un popover. Esto parece una especie de dependency injection.

Todo bien en teoría, pero simplemente no puedo entender dónde está ese gancho, o incluso si existe uno en cualquiera de los motores de validación. Ambos parecen decididos a asumir la responsabilidad de mostrar notificaciones con todo tipo de opciones elaboradas para colocación, envoltorios, estilos cuando todo lo que busco son los tipos de error (no necesariamente necesito el texto del mensaje) y el elemento se relaciona a. He encontrado ganchos para todo el formulario, no las notificaciones individuales.

Prefiero los sistemas de validación que usan clases para definir reglas, ya que funcionan muy bien con formularios creados dinámicamente.

Alguien tiene una solución o una idea mejor?

Eche un vistazo a las opciones de highlight y showErrors jQuery Validator , que le permitirán enganchar sus propios destacados de error personalizados que activan los popovers de Bootstrap.

Este es un ejemplo práctico:

 $('form').validate({ errorClass:'error', validClass:'success', errorElement:'span', highlight: function (element, errorClass, validClass) { $(element).parents("div[class='clearfix']").addClass(errorClass).removeClass(validClass); }, unhighlight: function (element, errorClass, validClass) { $(element).parents(".error").removeClass(errorClass).addClass(validClass); } }); 

enter image description here

Realmente no usa popovers bootstrap, pero se ve muy bien y es fácil de lograr.

ACTUALIZAR

Entonces, para tener validación de popover puedes usar este código:

 $("form").validate({ rules : { test : { minlength: 3 , required: true } }, showErrors: function(errorMap, errorList) { $.each(this.successList, function(index, value) { return $(value).popover("hide"); }); return $.each(errorList, function(index, value) { var _popover; _popover = $(value.element).popover({ trigger: "manual", placement: "top", content: value.message, template: "

" }); // Bootstrap 3.x : //_popover.data("bs.popover").options.content = value.message; // Bootstrap 2.x : _popover.data("popover").options.content = value.message; return $(value.element).popover("show"); }); } });

Obtienes algo como esto:

enter image description here

Mira el jsFiddle .

Chris Fulstow tenía razón, pero me tomó un tiempo, así que aquí está el código completo:

Esto muestra el popover en caso de error y oculta las tags de error predeterminadas:

 $('#login').validate({ highlight: function(element, errClass) { $(element).popover('show'); }, unhighlight: function(element, errClass) { $(element).popover('hide'); }, errorPlacement: function(err, element) { err.hide(); } }).form(); 

Esto configura el popover. Lo único que necesitas de esto es disparador: ‘manual’

 $('#password').popover({ placement: 'below', offset: 20, trigger: 'manual' }); 

Los atributos de título y contenido pasados ​​a popover no funcionaban, así que los especifiqué en línea en mi entrada #password con data-content = ‘Minimum 5 characters’ y data-original-title = ‘Invalid Password’. También necesita rel = ‘popover’ en su forma.

Esto funciona, pero el popover parpadea al deseleccionar. ¿Alguna idea de como arreglarlo?

Aquí hay un seguimiento de la excelente sugerencia de Varun Singh que evita que el problema de “parpadeo” de la validación intente constantemente “mostrarse” a pesar de que la ventana emergente ya está presente. Simplemente agregué una matriz de estados de error para capturar qué elementos muestran errores y cuáles no. ¡Funciona de maravilla!

 var errorStates = []; $('#LoginForm').validate({ errorClass:'error', validClass:'success', errorElement:'span', highlight: function (element, errorClass) { if($.inArray(element, errorStates) == -1){ errorStates[errorStates.length] = element; $(element).popover('show'); } }, unhighlight: function (element, errorClass, validClass) { if($.inArray(element, errorStates) != -1){ this.errorStates = $.grep(errorStates, function(value) { return value != errorStates; }); $(element).popover('hide'); } }, errorPlacement: function(err, element) { err.hide(); } }); $('#Login_unique_identifier').popover({ placement: 'right', offset: 20, trigger: 'manual' }); $('#Login_password').popover({ placement: 'right', offset: 20, trigger: 'manual' }); 

Esta extensión de jQuery para jQuery Validation Plugin (probada con la versión 1.9.0) hará el truco.

https://github.com/tonycoco/rails_template/blob/master/files/assets/javascripts/jquery.validate.bootstrap.js

Esto también agrega algunos mensajes de error de Rails-esk.

Prefiero cambiar el CSS de bootstrap. Acabo de agregar las clases de jQuery validate en el lugar correcto. field-validation-error y input-validation-error

  form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline, .field-validation-error { color: #b94a48; } form .clearfix.error input, form .clearfix.error textarea, .input-validation-error { color: #b94a48; border-color: #ee5f5b; } form .clearfix.error input:focus, form .clearfix.error textarea:focus, .input-validation-error:focus { border-color: #e9322d; -webkit-box-shadow: 0 0 6px #f8b9b7; -moz-box-shadow: 0 0 6px #f8b9b7; box-shadow: 0 0 6px #f8b9b7; } 

Así es como lo hice con Bootstrap 2.x y jQuery Validate 1.9

 $('#form-register').validate({ errorElement: 'span', errorClass:'help-inline', highlight: function (element, errorClass) { $(element).parent().parent().addClass('error'); }, unhighlight: function (element, errorClass) { $(element).parent().parent().removeClass('error'); }}); 

Por favor, eche un vistazo a lo siguiente:
https://gist.github.com/3030983
Creo que es el más simple de todos.

EDITAR

Código del enlace:

 $('form').validate({ rules: { numero: { required: true }, descricao: { minlength: 3, email: true, required: true } }, showErrors: function (errorMap, errorList) { $.each(this.successList, function (index, value) { $(value).popover('hide'); }); $.each(errorList, function (index, value) { console.log(value.message); var _popover = $(value.element).popover({ trigger: 'manual', placement: 'top', content: value.message, template: '

' }); _popover.data('popover').options.content = value.message; $(value.element).popover('show'); }); } });

¡Muchas gracias por el aviso! Aquí está mi versión para Bootstrap pero con Tooltips. En mi opinión, es más elegante que los popovers. Sé que la pregunta era sobre los popovers así que por favor no voten por este motivo. Tal vez a alguien le guste de esta manera. Me encanta cuando estoy buscando algo y encontré nuevas ideas sobre Stackoverflow. Nota: no es necesario ningún marcado en el formulario.

  $('#LoginForm').validate({ rules: { password: { required: true, minlength: 6 }, email_address: { required: true, email: true } }, messages: { password: { required: "Password is required", minlength: "Minimum length is 6 characters" }, email_address: { required: "Email address is required", email: "Email address is not valid" } }, submitHandler: function(form) { form.submit(); }, showErrors: function (errorMap, errorList) { $.each(this.successList, function (index, value) { $('#'+value.id+'').tooltip('destroy'); }); $.each(errorList, function (index, value) { $('#'+value.element.id+'').attr('title',value.message).tooltip({ placement: 'bottom', trigger: 'manual', delay: { show: 500, hide: 5000 } }).tooltip('show'); }); } }); 

Así es como lo hice suceder. Pero se trata de hacer 2 cambios en el script de validación (obtuve el código de bootstrap 1.4 aquí y luego lo modifiqué – http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin- for-twitter-bootstrap / )

Mi llamado a validar:

  $("#loginForm").validate({ errorClass: "control-group error", validClass: "control-group success", errorElement: "span", // class='help-inline' highlight: function(element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).parent("div").parent("div").removeClass(validClass).addClass(errorClass); } else { $(element).parent("div").parent("div").removeClass(validClass).addClass(errorClass); } }, unhighlight: function(element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).parent("div").parent("div").removeClass(errorClass).addClass(validClass); } else { $(element).parent("div").parent("div").removeClass(errorClass).addClass(validClass); } } }); 

Entonces necesitas cambiar 2 cosas en jquery.validate.js
1. aplique esta solución – https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. Después de la línea 647 (en la función showLabel, crear la parte de la etiqueta) después de la línea .addClass(this.settings.errorClass) add line: .addClass("help-inline")
Alguien puede encontrar la manera de aplicar la segunda corrección en la función de validación, pero no he encontrado una forma, ya que se llama a showLabel después del resaltado.

Esto es lo que puse en mi validación para cumplir con las pautas de Twitter Bootstrap. El mensaje de validación de error se coloca en una y queremos resaltar el contenedor externo como un error o success :

 errorClass:'help-inline', errorElement:'span', highlight: function (element, errorClass, validClass) { $(element).parents("div.clearfix").addClass('error').removeClass('success'); }, unhighlight: function (element, errorClass, validClass) { $(element).parents(".error").removeClass('error').addClass('success'); } 

Aquí hay una actualización de la excelente respuesta anterior de Kenny Meyer . Hubo un par de problemas que impidieron que funcionara para mí, que he tratado en este fragmento:

 showErrors: function (errorMap, errorList) { $.each(this.successList, function (index, element) { return $(element).popover("destroy"); }); $.each(errorList, function (index, error) { var ele = $(error.element); //Instead of referencing the popover directly, I use the element that is the target for the popover ele.popover({ trigger: "manual", placement: "top", content: function(){ //use a function to assign the error message to content return error.message }, template: '

' }); //bs.popover must be used, not just popover ele.data("bs.popover").options.content = error.message; return $(error.element).popover("show"); }); }

No estoy seguro de si esto es relevante para la discusión porque el cartel original pidió ganchos para mostrar / ocultar popovers bootstrap.

Estaba buscando una validación simple y los popovers no importaban. Una publicación relacionada y la primera en los resultados de búsqueda de Google ya ha sido marcada como duplicada de esta pregunta. Por lo tanto, tenía sentido mencionar este excelente JQValidation JS @ ReactiveRaven, acertadamente llamado jqBootstrapValidation, que se combina bien con Twitter Bootstrap. La configuración solo toma unos minutos. Descargue aquí .

Espero que esto agregue valor.

tl; dr evita tener que enumerar los popovers explícitos utilizando un mapa hash para almacenar los identificadores de los elementos y crear popovers sobre la marcha (enmascara los enfoques de Jeffrey Gilbert y Kenny Meyer).

Aquí está mi opinión, que corrige el problema de parpadeo mencionado por otros, pero a diferencia de la respuesta de @Jeffrey Gilbert, no usa una lista ( errorStates ) sino que usa un mapa de error. Hash maps FTW. Creo que recuerdo haber leído en alguna parte que todos los problemas en CS se pueden resolver con un hash map 🙂

 var err_map = new Object(); // <--- nb $("form#set_draws").validate({ rules: { myinput: { required: true, number: true }, }, showErrors: function(errorMap, errorList) { $.each(this.successList, function(index, value) { if (value.id in err_map) { var k = err_map[value.id]; delete err_map[value.id]; // so validation can transition between valid/invalid states k.popover("hide"); } }); return $.each(errorList, function(index, value) { var element = $(value.element); if( ! (value.element.id in err_map) ) { var _popover = element.popover({ trigger: "manual", placement: "top", content: value.message, template: "

" }); _popover.data("popover").options.content = value.message; err_map[value.element.id] = _popover; return err_map[value.element.id].popover("show"); } }); } });

Gracias a todos los demás que publicaron ideas sobre esto.

Mira esto: https://github.com/mingliangfeng/jquery.validate.bootstrap.popover

Muestra cómo usar Bootstrap popover css, en lugar de JS. El emergente del método JS causará un parpadeo.

Si usa el código anterior de Kenny Meyer para ventanas emergentes, tenga cuidado de que las reglas que verifican el contenido de un campo pero que no son necesarias, como una URL válida, hagan que la ventana emergente no desaparezca al borrar el campo. Vea a continuación onkeyup para la solución. Si alguien tiene una mejor solución, por favor publíquela.

 onkeyup: function(element, event) { if($(element).valid()) { return $(element).popover("hide"); } }