如何使用 Twitter Bootstrap 弹出框进行 jQuery 验证通知?

Posted

技术标签:

【中文标题】如何使用 Twitter Bootstrap 弹出框进行 jQuery 验证通知?【英文标题】:How to use Twitter Bootstrap popovers for jQuery validation notifications? 【发布时间】:2012-01-16 09:23:27 【问题描述】:

我可以很容易地使用bootstrap 使弹出框出现,我还可以使用标准jQuery validation plugin 或jQuery validation engine 进行验证,但我不知道如何将一个输入另一个。

我认为我需要的是一些钩子,当它想要显示通知时,验证器会调用它,给它一个闭包,将消息和目标元素传递给弹出框。这似乎是一种依赖注入。

理论上一切都很好,但我就是不知道那个钩子在哪里,或者即使在任一验证引擎中都存在这个钩子。当我所追求的只是错误类型(我什至不需要消息文本)和它相关的元素时,他们似乎都打算负责显示带有各种精心设计的放置、包装、样式选项的通知到。我发现了整个表单的钩子,而不是单个通知。

我更喜欢使用类来定义规则的验证系统,因为它们可以很好地与动态创建的表单配合使用。

谁有解决方案或更好的主意?

【问题讨论】:

【参考方案1】:

这是一个动手示例:

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

【讨论】:

赞成,因为这是我正在寻找的方向。 :-) 查看我的答案以获取变体。 如果是多级表格怎么办 请注意,最新版本的 Bootstrap 不再有 .data("popover") 键。也许为了避免冲突,他们将密钥更改为“bs.popover”。我花了一段时间才弄明白为什么我得到一个 undefined 错误。所以现在你需要在上面的代码中使用 _popover.data("bs.popover").options.content = value.message; 除了必填字段外,我如何在其他错误类型上显示弹出窗口。我的意思是说我如何自定义它以仅在特定规则上显示错误。 实际上还有一个小问题,您也可以在 jsFiddle 中轻松查看。如果该字段不是必需的并且某些规则被破坏,则会显示弹出框,但是如果我清空该字段并专注于另一个字段,则弹出框仍然存在。 successList 上的第一个循环永远不会被调用,因此弹出框在进入“显示”状态后永远不会处于“隐藏”状态。有什么我们可以做的吗?【参考方案2】:

看看highlightshowErrors jQuery Validator options,它们可以让你加入你自己的自定义错误亮点,触发引导弹出框。

【讨论】:

太好了,谢谢。 highlight 和 unhighlight 是我想要的。【参考方案3】:

Chris Fulstow 是对的,但我还是花了一些时间,所以这里是完整的代码:

这会显示错误弹出框,并隐藏默认错误标签:

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

这会设置弹出框。您唯一需要的是 trigger: 'manual'

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

传递给 popover 的标题和内容属性不起作用,因此我在 #password 输入中将它们内联指定为 data-content='Minimum 5 characters' 和 data-original-title='Invalid Password'。您的表单中还需要 rel='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'
);

【讨论】:

这是此页面上唯一对我有用的答案。可惜它没有被更多人投票。 这是否意味着您需要为要验证的每个字段定义一个明确的popover?如果是这样,那就是坚果 对于大多数用例,我希望这是完全可以接受的。如果您有更优化的解决方案,请随时添加:)【参考方案5】:

这个用于 jQuery Validation Plugin 的 jQuery 扩展(使用 1.9.0 版测试)可以解决问题。

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

这也添加了一些 Rails-esk 错误消息。

【讨论】:

这很棒。超级有帮助。现在要弄清楚如何为 TOS 复选框获取适当的消息...【参考方案6】:

我更喜欢更改引导程序的 CSS。刚刚在正确的地方添加了 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;

【讨论】:

这种方法看起来最适合我 :) 。我也是这么想的【参考方案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 我认为这是最简单的。

编辑

链接代码:

$('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更优雅。【参考方案9】:

非常感谢您的提醒!这是我的 Bootstrap 版本,但带有工具提示。在我看来,它比popovers更优雅。我知道这个问题是针对弹出框的,所以请不要因此而投反对票。也许有人会喜欢这种方式。当我在寻找一些东西时,我喜欢在 *** 上找到新的想法。注意:表格上不需要标记。

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

            );

        

    ); 

【讨论】:

我尝试使用您的方法,但开始出现错误。问题是,如果您使用 Jquery UI,您会遇到冲突,因为两者都使用工具提示。我知道有一个解决方案,但只是想让其他用户知道。 +1 对于 jQuery UI,请注意!您必须将自定义下载(jQueryUI 或 Bootstrap)配置为不包含 Tooltip JS 函数。如果你没有这样做,任何工具提示都会发生冲突。 嘿,我试图将您的代码与正则表达式一起使用,但在 ***.com/questions/16087351/… 处发生错误。你觉得你能帮上忙吗? :) @psharma 与引导程序或工具提示无关。您的错误是您的规则声明,因为您得到了问题的答案。错误消息说:术语未定义! 出于某种原因,这是唯一对我有用的解决方案。谢谢!【参考方案10】:

这就是我实现它的方式。但它涉及对验证脚本进行 2 处更改(我在这里获得了 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);
    
  
);

然后你需要在 jquery.validate.js 中改变两件事 1. 应用此修复 - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a 2. 在第647行之后(在showLabel函数中,创建标签部分)在.addClass(this.settings.errorClass)行之后添加行:.addClass("help-inline") 有人可能会找到一种方法来在 validate 函数中应用第二个修复,但我还没有找到方法,因为 showLabel 是在 highlight 之后调用的。

【讨论】:

【参考方案11】:

这是我在验证中添加的内容,以符合 Twitter Bootstrap 指南。错误验证消息放在&lt;span class=help-inline&gt; 中,我们希望将外部容器突出显示为errorsuccess

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】:

这是Kenny Meyer's excellent answer above 的更新。有几个问题使它无法为我工作,我已经在这个 sn-p 中解决了这些问题:

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

【讨论】:

感谢您的倡议。如我所见,代码发生了很大变化:-)【参考方案13】:

不确定这是否与讨论相关,因为原始发帖人要求使用挂钩来显示/隐藏引导弹出框。

我正在寻找简单的验证,弹出框并不重要。 related post 和谷歌搜索结果中的第一个已被标记为此问题的重复项。因此,有必要提及这个出色的 @ReactiveRaven 的 jqValidation JS,恰当地称为 jqBootstrapValidation,它与 Twitter Bootstrap 结合得很好。安装只需几分钟。下载here。

希望这能增加价值。

【讨论】:

【参考方案14】:

tl;dr 通过使用哈希映射来存储元素的 id 并即时创建弹出框(混搭 Jeffrey Gilbert 和 Kenny Meyer 的方法),避免需要枚举显式弹出框。

这是我的看法,它解决了其他人提到的闪烁问题,但与@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");
      
    );
  
);

感谢所有对此发表想法的其他人。

【讨论】:

【参考方案15】:

查看:https://github.com/mingliangfeng/jquery.validate.bootstrap.popover

它展示了如何使用 Bootstrap popover css,而不是 JS。 JS 方法弹出会导致闪烁问题。

【讨论】:

【参考方案16】:

如果将上述 Kenny Meyer 代码用于弹出窗口,请注意检查字段内容但不是必需的规则(例如有效 URL)将导致弹出窗口在清除字段时不会消失。有关解决方案,请参见下面的 onkeyup。如果有人有更好的解决方案,请发布。

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

【讨论】:

以上是关于如何使用 Twitter Bootstrap 弹出框进行 jQuery 验证通知?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击外部来关闭 Twitter Bootstrap 弹出窗口?

如何在鼠标移入之前保持 Twitter Bootstrap Popover 打开?

Twitter Bootstrap 弹出框不适用于动态生成的内容

如何在 twitter-bootstrap-3 模态框中使用复选框

Twitter Bootstrap 弹出框/工具提示错误与移动设备?

Twitter Bootstrap 弹出框内的 HTML