Как использовать Twitter Bootstrap popovers для уведомлений проверки jQuery?

Я могу сделать popovers появляются с помощью bootstrap достаточно легко, и я также могу делать проверки, используя стандарт проверка jQuery плагин или механизм проверки jQuery, но я не могу понять, как кормить друг друга.

Я думаю, что мне нужен какой-то крюк, который вызывается валидатором, когда он хочет отобразить уведомление, дать ему закрытие, которое передает сообщение и целевой элемент в popover. Это кажется своего рода инъекция зависимости.

все хорошо в теории, но я просто не могу понять, где этот крюк, или даже если он существует в любом механизме проверки. Они оба, похоже, намерены взять на себя ответственность за отображение уведомлений со всеми видами сложных опций для размещения, оболочек, стилей, когда все, что мне нужно, - это тип(ы) ошибки (мне не обязательно даже нужен текст сообщения) и элемент, к которому он относится. Я нашел крючки для всей формы, а не для отдельного человека уведомления.

Я предпочитаю системы проверки, которые используют классы для определения правил, поскольку они хорошо играют с динамически созданными формами.

У кого-нибудь есть решение или идея получше?

16 ответов


посмотри highlight и showErrors параметры валидатора jQuery, они позволят вам подключить собственные пользовательские ошибки, которые запускают всплывающие окна начальной загрузки.


это практический пример:

$('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

на самом деле он не использует bootstrap popovers, но выглядит очень красиво и легко достичь.

обновление

Итак, для проверки popover вы можете использовать этот код:

$("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");
    });
  }
});

получится что-то вроде этого:

enter image description here

Проверьте jsFiddle.


Крис Fulstow был прав, но он все-таки взял меня некоторое время, так что вот полный код:

это показывает всплывающее сообщение об ошибке и скрывает метки ошибок по умолчанию:

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

это устанавливает popover. Единственное, что вам нужно от этого, это триггер: 'manual'

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

атрибуты title и content, переданные в popover, не работали, поэтому я указал их в своем # password input с data-content= 'минимум 5 символов' и data-original-title= 'неверный пароль'. Вам также нужно rel= 'popover' в вашей форме.

это работает, но popover мерцает при отмене выбора. Есть идеи, как это исправить?


вот продолжение отличного предложения от Варуна Сингха, которое предотвращает проблему" мерцания "проверки, постоянно пытающуюся" показать", хотя всплывающее окно уже присутствует. Я просто добавил массив состояний ошибок для захвата, какие элементы показывают ошибки, а какие нет. Работает как шарм!

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

Это расширение jQuery для плагина проверки jQuery (протестировано с версией 1.9.0) сделает трюк.

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

Это также добавляет в некоторые сообщения об ошибках Rails-esk.


Я предпочитаю изменить CSS bootstrap. Просто добавлены классы jQuery validate в нужном месте. поле-проверка-ошибка и ввод-проверка-ошибка

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

вот как я это сделал с Bootstrap 2.x и jQuery проверяют 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');
    }});

пожалуйста, взгляните на следующее:
- https://gist.github.com/3030983
Я думаю, что это проще всего.

редактировать

код ссылки:

$('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');

        });

    }

});

большое спасибо за головы! Вот моя версия для Bootstrap, но с подсказками. По-моему, это элегантнее, чем поповеры. Я знаю, что вопрос был для popovers, поэтому, пожалуйста, не голосуйте по этой причине. Может, кому-то это понравится. Я люблю, когда я ищу что-то, и я нашел новые идеи о Stackoverflow. Примечание: нет разметки на форме.

    $('#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');

            });

        }

    }); 

вот как я это сделал. Но это включает в себя внесение 2 изменений в скрипт validate (я получил код для bootstrap 1.4 здесь, а затем изменил его - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin-for-twitter-bootstrap/)

мой звонок для проверки:

    $("#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);
    }
  }
});

тогда вам нужно изменить 2 вещи в jquery.утверждать.js
1. применить это исправление - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. После строки 647 (в функции showLabel создайте часть метки) после строки .addClass(this.settings.errorClass) добавить строку: .addClass("help-inline")
Кто-то может найти способ применить второе исправление в функции validate, но я не нашел способ, так как showLabel вызывается после выделения.


это то, что я положил в свою проверку, чтобы соответствовать рекомендациям Twitter Bootstrap. Сообщение об ошибке проверки в <span class=help-inline> и мы хотим выделить внешний контейнер как error или 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');
}

вот обновление до отличный ответ Кенни Мейера выше. Было несколько проблем, которые помешали ему работать на меня, которые я рассмотрел в этом фрагменте:

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

Не уверен, что это имеет отношение к обсуждению, потому что оригинальный плакат попросил крючки, чтобы показать/скрыть бутстрап popovers.

Я искал простую проверку, и popovers не имело значения. А похожие статьи и первый в результатах поиска google уже был отмечен дубликатом этого вопроса. Поэтому имело смысл упомянуть этот отличный jqvalidation js @ReactiveRaven, метко называемый jqBootstrapValidation, который хорошо сочетается с Twitter Bootstrap. Установка занимает всего несколько минут. Скачать здесь.

надеюсь, это добавит ценность.


tl; dr избегайте необходимости перечислять явные всплывающие окна, используя хэш-карту для хранения идентификаторов элементов и создания всплывающих окон "на лету" (подходы Джеффри Гилберта и Кенни Мейера).

вот мой взгляд, который исправляет проблему мерцания, упомянутую другими, но в отличие от ответа @Jeffrey Gilbert, не использует список (errorStates), но скорее использует ошибки карта. Хэш-карты стандарта. Кажется, я где-то читал, что каждая проблема в CS можно решить с помощью хэш-карты:)

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

спасибо всем, кто разместил идеи по этому поводу.


проверьте это:https://github.com/mingliangfeng/jquery.validate.bootstrap.popover

Он показывает, как использовать Bootstrap popover css вместо JS. Всплывающее окно метода JS вызовет проблему мигания.


Если вы используете приведенный выше код Кенни Мейера для всплывающих окон, будьте осторожны, что правила, которые проверяют содержимое поля, но не требуются, такие как действительный URL, заставят всплывающее окно не исчезнуть при очистке поля. См. ниже onkeyup для решения. Если у кого-то есть лучшее решение, пожалуйста, напишите.

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