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

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

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

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

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

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


person Synchro    schedule 09.12.2011    source источник


Ответы (16)


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

person Chris Fulstow    schedule 09.12.2011
comment
Отлично, спасибо. выделить и убрать выделение - вот что я искал. - person Synchro; 09.12.2011

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

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

введите описание изображения здесь

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

ОБНОВЛЕНИЕ

Итак, чтобы проверить всплывающее окно, вы можете использовать этот код:

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

Вы получите что-то вроде этого:

введите описание изображения здесь

Ознакомьтесь с jsFiddle.

person Kenny Meyer    schedule 30.12.2011
comment
Проголосовали за, потому что это именно то, что я искал. :-) Вариант см. В моем ответе. - person namin; 15.03.2012
comment
Что делать, если это многоступенчатая форма - person Tachyons; 01.04.2013
comment
Замечу, что в последней версии Bootstrap больше нет ключа .data (popover). Возможно, чтобы избежать коллизии, они изменили ключ на bs.popover. Мне потребовалось время, чтобы понять, почему я получаю ошибку undefined. Итак, теперь вам нужно использовать _popover.data (bs.popover) .options.content = value.message; в приведенном выше коде. - person davidethell; 11.09.2013
comment
Как я могу отобразить всплывающее окно при другом типе ошибки, кроме обязательных полей. Я хочу сказать, как я могу настроить его, чтобы отображать ошибку только по определенным правилам. - person arjun; 20.12.2013
comment
На самом деле есть небольшая проблема, которую вы также можете легко проверить в jsFiddle. Если поле не требуется и какое-то правило нарушено, всплывающее окно появляется, НО если я очищаю поле и фокусируюсь на другом поле, всплывающее окно все еще там. Первый цикл в successList никогда не вызывается, поэтому всплывающее окно никогда не находится в состоянии скрытия после того, как оно переходит в состояние отображения. Что мы можем с этим поделать? - person G4bri3l; 10.04.2014

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

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

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

Это устанавливает всплывающее окно. Единственное, что вам нужно от этого, - это триггер: «вручную».

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

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

Это работает, но всплывающее окно мигает после отмены выбора. Есть идеи, как это исправить?

person Varun Singh    schedule 05.01.2012

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

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'
});
person Jeffrey Gilbert    schedule 22.12.2012
comment
Это был единственный ответ на этой странице, который сработал для меня. Жаль, что за это больше не проголосовали. - person alastairs; 09.02.2013
comment
Разве это не означает, что вам нужно явно определять popover для каждого поля, которое вы хотите проверить? Если так, то это чокнутый. - person ; 12.06.2013
comment
Я ожидал, что для большинства случаев использования это вполне приемлемо. Если у вас есть более оптимальное решение, смело добавляйте его :) - person Jeffrey Gilbert; 29.01.2014

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

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

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

person tonycoco    schedule 26.04.2012
comment
Отлично. Очень полезно. Теперь выясним, как получить соответствующее сообщение для флажка TOS ... - person tig; 14.06.2012

Я предпочитаю изменить CSS начальной загрузки. Просто добавили классы проверки 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;
}
person Alberto Chvaicer    schedule 04.01.2012
comment
Мне этот подход подходит лучше всего :). Это тоже то, о чем я думал - person Freshblood; 12.05.2012

Вот как я это сделал с 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');
    }});
person Jamie R Rytlewski    schedule 04.04.2012

Обратите внимание на следующее:
- 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');

        });

    }

});
person Codemator    schedule 22.09.2012
comment
Большое спасибо за внимание! Посмотрите мою версию для Bootstrap, но с всплывающими подсказками. На мой взгляд, это более элегантно, чем поповеры. - person Adrian P.; 27.02.2013

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

            });

        }

    }); 
person Adrian P.    schedule 27.02.2013
comment
Я пытался использовать ваш подход, но начинал получать ошибку. и проблема в том, что если вы используете JQuery UI, вы получите конфликт, потому что оба используют всплывающую подсказку. Я знаю, что для этого есть решение, но просто хочу, чтобы другие пользователи знали об этом. - person Richard Pérez; 28.02.2013
comment
+1 За поддержку jQuery UI! Вам нужно будет настроить пользовательскую загрузку (jQueryUI или Bootstrap), чтобы НЕ включать функции Tooltip JS. В любом случае это будет конфликт для любой всплывающей подсказки, если вы этого не сделаете. - person Adrian P.; 01.03.2013
comment
привет, я пытался использовать ваш код с регулярным выражением, и у меня возникла ошибка stackoverflow.com/questions/16087351/. Вы думаете, что можете помочь? :) - person psharma; 18.04.2013
comment
@psharma Ничего общего с начальной загрузкой или всплывающей подсказкой. Ваша ошибка - это объявление вашего правила, поскольку вы получили ответ на свой вопрос. в сообщении об ошибке сказано: условия не определены! - person Adrian P.; 27.04.2013
comment
По какой-то причине это единственное решение, которое у меня сработало. Спасибо! - person suchanoob; 12.09.2016

Вот как я это сделал. Но это предполагает внесение 2 изменений в сценарий проверки (я получил здесь код для начальной загрузки 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") < br /> Кто-то может найти способ применить второе исправление в функции проверки, но я не нашел способа, так как showLabel вызывается после выделения.

person Andrej Bergant    schedule 07.02.2012

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

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

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");
        });
    }
person tofirius    schedule 01.08.2016
comment
Спасибо за инициативу. Как я вижу, код сильно изменился :-) - person Kenny Meyer; 22.04.2018

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

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

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

person uchamp    schedule 27.02.2013

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

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

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

person Community    schedule 12.06.2013


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

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