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


84

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

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

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

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

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

Ответы:


21

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


Отлично, спасибо. выделить и убрать выделение - вот что я искал.
Synchro,

80

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

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


3
Проголосовали, потому что это именно то, что я искал. :-) Вариант см. В моем ответе.
namin

Что делать, если это многоступенчатая форма
Тахионы

4
Замечу, что в последней версии Bootstrap больше нет ключа .data ("popover"). Возможно, чтобы избежать коллизии, поменяли ключ на "bs.popover". Мне потребовалось время, чтобы понять, почему я получаю неопределенную ошибку. Итак, теперь вам нужно использовать _popover.data ("bs.popover"). Options.content = value.message; в коде выше.
Дэвидетелл

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

На самом деле есть небольшая проблема, которую вы также можете легко проверить в jsFiddle. Если поле не требуется и какое-то правило нарушено, всплывающее окно появляется, НО если я очищаю поле и сосредотачиваюсь на другом поле, всплывающее окно все еще там. Первый цикл в successList никогда не вызывается, поэтому всплывающее окно никогда не находится в состоянии «скрытия» после того, как оно переходит в состояние «показать». Что мы можем с этим поделать?
G4bri3l

9

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

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

$('#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' в вашей форме.

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


6

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

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

Это был единственный ответ на этой странице, который работал у меня. Жаль, что за это больше не проголосовали.
alastairs

1
Разве это не означает, что вам нужно явно определять popoverкаждое поле, которое вы хотите проверить? Если так, то это чушь .
g33kz0r

Я ожидал, что для большинства случаев использования это вполне приемлемо. Если у вас есть более оптимальное решение, не стесняйтесь добавлять его :)
Джеффри Гилберт

5

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

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

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


Это замечательно. Очень полезно. Теперь выясним, как получить соответствующее сообщение для флажка TOS ...
tig

3

Я предпочитаю изменить 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;
}

Мне этот подход подходит лучше всего :). Я тоже об этом думал
Freshblood

3

Вот как я это сделал с 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');
    }});

3

Обратите внимание на следующее:
- 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, но с всплывающими подсказками. На мой взгляд, это более элегантно, чем поповеры.
Адриан П.

3

Большое спасибо за внимание! Вот моя версия для 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');

            });

        }

    }); 

1
Я пытался использовать ваш подход, но начинал получать ошибку. и проблема в том, что если вы используете JQuery UI, вы получите конфликт, потому что оба используют всплывающую подсказку. Я знаю, что для этого есть решение, но просто хочу, чтобы другие пользователи знали об этом.
Ричард Перес

+1 За поддержку jQuery UI! Вам нужно будет настроить собственную загрузку (jQueryUI или Bootstrap), чтобы НЕ включать функции Tooltip JS. В любом случае, если вы этого не сделаете, это вызовет конфликт для любой подсказки.
Адриан П.

привет, я пытался использовать ваш код с регулярным выражением, и у меня возникла ошибка на stackoverflow.com/questions/16087351/… . Вы думаете, что можете помочь? :)
psharma

@psharma Ничего общего с начальной загрузкой или всплывающей подсказкой. Ваша ошибка - это объявление вашего правила, поскольку вы получили ответ на свой вопрос. в сообщении об ошибке сказано: термины не определены!
Адриан П.

По какой-то причине это единственное решение, которое у меня сработало. Благодаря!
suchanoob

2

Вот как я это сделал. Но это включает в себя внесение 2 изменений в сценарий проверки (здесь я получил код для начальной загрузки 1.4, а затем изменил его - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin- для-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 вызывается после выделения.


2

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

2

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

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

Спасибо за инициативу. Код сильно изменился, как я вижу :-)
Кенни Мейер

1

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

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

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


1

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

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

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



0

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

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.