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

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

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

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

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

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

Ответ 1

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

Ответ 2

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

$('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, но выглядит очень красиво и легко достигается.

UPDATE

Итак, чтобы иметь проверку 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.

Ответ 3

У Криса Фулстоу было все правильно, но мне все равно потребовалось некоторое время, поэтому полный код:

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

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

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

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

Ответ 4

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

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

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

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

Ответ 7

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

Ответ 8

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

EDIT

Код по ссылке:

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

        });

    }

});

Ответ 9

Большое спасибо за головы! Вот моя версия для Bootstrap, но с подсказками. По-моему, это более элегантно, чем popovers. Я знаю, что вопрос был для 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');

            });

        }

    }); 

Ответ 10

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

Ответ 11

Это то, что я поставил в своей проверке, чтобы соответствовать рекомендациям 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');
}

Ответ 12

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

Я искал простую проверку, и popovers не имеет значения. A связанный пост, и первый в результатах поиска Google уже был отмечен дубликатом этого вопроса. Поэтому имеет смысл упомянуть об этом превосходном @ReactiveRaven jqValidation JS, точно названном jqBootstrapValidation, который хорошо сочетается с Twitter Bootstrap. Настройка занимает всего несколько минут. Загрузите здесь.

Надеемся, что это добавит ценность.

Ответ 13

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

Здесь мой ответ, который исправляет мерцающую проблему, упомянутую другими, но в отличие от @Jeffrey Gilbert отвечает, не использует список (errorStates), а скорее использует карту ошибок. Хэш-карты FTW. Я думаю, что я помню, где-то читал, что каждая проблема в 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");
      }
    });
  }
});

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

Ответ 15

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

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

Ответ 16

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

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