Cómo utilizar Twitter Bootstrap popovers para las notificaciones de validación de jQuery?


Puedo hacer que aparezcan popovers usando bootstrap con bastante facilidad, y también puedo hacer validaciones usando el complemento de validación jQuery estándar o el motor de validación jQuery , pero no puedo averiguar cómo alimentar uno al otro.

Creo que lo que necesito es algún gancho que es llamado por el validador cuando quiere mostrar una notificación, darle un cierre que pase el mensaje y el elemento de destino a una ventana emergente. Esto parece una especie de dependencia inyección.

Todo bien en teoría, pero simplemente no puedo averiguar 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 la colocación, envoltorios, estilos cuando todo lo que busco es el tipo de error(s) (no necesariamente ni siquiera necesito texto del mensaje) y el elemento con el que se relaciona. He encontrado ganchos para todo el formulario, no para las notificaciones individuales.

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

Alguien tiene una solución o una idea mejor?

Author: Synchro, 2011-12-09

16 answers

Echa un vistazo a la highlight y showErrors jQuery Validator options , estos le permitirán enganchar sus propios resaltados de errores personalizados que activan popovers de arranque.

 20
Author: Chris Fulstow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-09 00:13:25

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); 
    }
});

introduzca la descripción de la imagen aquí

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

UPDATE

Por lo tanto, para tener validación popover puede utilizar 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: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
      });
      // 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:

introduzca la descripción de la imagen aquí

Mira el jsFiddle.

 80
Author: Kenny Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-14 13:33:06

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

Esto muestra la ventana emergente en caso de error y oculta las etiquetas 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 necesita de esto es trigger:'manual'

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

Los atributos title y content pasados a popover no funcionaban, así que los especificé en línea en mi entrada #password con data-content='Mínimo 5 caracteres' y data-original-title='Invalid Password'. Usted también necesita rel = 'popover' en su formulario.

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

 9
Author: Varun Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 06:15:34

Aquí hay un seguimiento de la excelente sugerencia de Varun Singh que evita el "parpadeo" cuestión de la validación constantemente tratando de "mostrar" a pesar de que la ventana emergente ya está presente. Simplemente he agregado una matriz de estados de error para capturar qué elementos muestran errores y cuáles no.

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'
});
 6
Author: Jeffrey Gilbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-22 23:26:19

Esta extensión de jQuery para el plugin de validación de jQuery (probado 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 añade algunos mensajes de error de Rails-esk.

 5
Author: tonycoco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-26 19:46:49

Prefiero cambiar el CSS de bootstrap. Acaba de añadir las clases de validación de jQuery en el lugar correcto. field-validation-error and 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;
}
 3
Author: Alberto Chvaicer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-04 12:43:42

Así es como lo hice con Bootstrap 2.x y jQuery Validan 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');
    }});
 3
Author: Jamie R Rytlewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 18:44:48

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: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            _popover.data('popover').options.content = value.message;

            $(value.element).popover('show');

        });

    }

});
 3
Author: Codemator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-22 21:38:03

Muchas gracias por el aviso! Aquí está mi versión para Bootstrap pero con Tooltips. En mi opinión es más elegante que popovers. Sé que la pregunta era para popovers, así que por favor no voten en contra por esta razón. Tal vez a alguien le guste así. Me encanta cuando estoy buscando algo y encontré nuevas ideas en 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');

            });

        }

    }); 
 3
Author: Adrian P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-27 03:13:47

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

Mi llamada para 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.validar.js
1. aplicar esta corrección - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. Después de la línea 647 (en la función showLabel, create label part) después de la línea .addClass(this.settings.errorClass) agregar línea: .addClass("help-inline")
Tal vez alguien pueda encontrar una manera de aplicar la segunda corrección en la función validate, pero yo no he encontrado una manera, ya que showLabel se llama después de highlight.

 2
Author: Andrej Bergant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-07 14:37:51

Esto es lo que puse en mi validación para cumplir con las pautas de Bootstrap de Twitter. El mensaje de validación de error se coloca en un <span class=help-inline> y queremos resaltar el contenedor exterior 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');
}
 2
Author: namin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-15 11:06:35

Aquí hay una actualización de La excelente respuesta de Kenny Meyer anterior. Hubo un par de problemas que impidieron que funcionara para mí, que he abordado 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: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            //bs.popover must be used, not just popover
            ele.data("bs.popover").options.content = error.message;

            return $(error.element).popover("show");
        });
    }
 2
Author: tofirius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:45:38

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

Estaba buscando validación simple y popovers no importaba. Un post relacionado y el primero en los resultados de búsqueda de Google ya ha sido marcado duplicado de esta pregunta. Así que tenía sentido mencionar esta excelente jqValidation JS de @ReactiveRaven, acertadamente llamada jqBootstrapValidation, que combina bien con Twitter Bootstrap. La configuración toma unos pocos sólo minutos. Descargar aquí.

Espero que esto añada valor.

 1
Author: uchamp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:45:38

Tl; dr evite la necesidad de enumerar popovers explícitos mediante el uso de un mapa hash para almacenar los id de los elementos, y la creación de popovers sobre la marcha (mashup Jeffrey Gilbert y Kenny Meyer enfoques).

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 cada problema en CS se puede resolver con un mapa hash:)

var err_map = new Object();     // <--- n.b.
$("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: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
        });
        _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.

 1
Author: g33kz0r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-12 03:54:21

Checkout this: https://github.com/mingliangfeng/jquery.validate.bootstrap.popover

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

 1
Author: Andrew Feng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-11 13:14:55

Si usa el código de Kenny Meyer anterior para ventanas emergentes, tenga en cuenta que las reglas que comprueban el contenido de un campo pero no son obligatorias, como una URL válida, harán que la ventana emergente no desaparezca al borrar el campo. Ver a continuación onkeyup para la solución. Si alguien tiene una solución mejor, por favor publique.

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
 0
Author: monsoon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-14 16:41:16