首页 > 解决方案 > 延迟验证,直到用户选择输入组中的所有输入

问题描述

我的表单有一组三个复选框。用户必须至少选择以下三个选项之一:

<form id="myform" class="validated-form" novalidate="novalidate">
  <div id="fname" class="btn-group btn-group-toggle" data-toggle="buttons">
    <label>
      a
      <input type="checkbox" value="a" name="fname"/>
    </label>
    <label>
      b
      <input type="checkbox" value="b" name="fname"/>
    </label>
    <label>
      c
      <input type="checkbox" value="c" name="fname"/>
    </label>  
  </div>
</form>

我正在使用以下onfocusout回调来验证复选框组:

onfocusout: function(element) {
  
  if($(element).prop('type') == 'checkbox') {
        this.element(element);
      }

  }

请参阅JSFiddle


问题:当用户选择选项卡时,我希望验证器等到他们完全退出组(即当所有三个复选框都失去焦点时)再验证它。


我的第一次尝试是修改上述回调中的 if 语句,以包含一个条件,该条件选择组内所有具有焦点的元素,然后检查结果对象数组的长度是否为 0,如下所示:

onfocusout: function(element) {
  
   if($(element).prop('type') == 'checkbox' && $(element).closest('.btn-group').find('label:focus').length == 0) {
        this.element(element);
      }
  }

但是由于一个元素失去焦点和另一个元素接收焦点之间存在延迟,因此上述方法不起作用。我认为这是由于在被验证的输入失去焦点并且新元素获得焦点之前回调触发。此时,没有元素处于焦点位置,因此 if 语句条件的计算结果始终为true。出于同样的原因,我无法检测到焦点已转移哪个元素(因此我无法检查新聚焦的元素是否是复选框组的一部分)。

所以我的下一个尝试是使用setTimeout

onfocusout: function(element) {
  
  setTimeout(function() {
    if($(element).prop('type') == 'checkbox' && $(element).closest('.btn-group').find('label:focus').length == 0) {
        this.element(element);
      }
  }, 1);
  }

这似乎完全关闭了验证- 从一个复选框切换到另一个不会触发验证,但也不会完全退出复选框组。我用错了吗?(在小提琴中,它似乎没有效果。)

这个问题有更好的解决方案还是我试图解决错误的问题?

注意:我不能使用onclick回调,因为它与我在实际表单中使用的小部件不兼容。我更喜欢onfocusoutover的感觉,onclick因为它更符合 Validate 插件的默认行为。

标签: javascriptjqueryformsvalidationjquery-validate

解决方案


我曾经确定哪个元素获得了焦点并修改了 if 语句以仅在失去焦点的复选框的名称与复选框的名称不匹配event.relatedTarget时才触发验证:relatedTarget

onfocusout: function(element, event) {
  
    if($(element).prop('type') == 'checkbox' && $(event.relatedTarget).attr('name') != $(element).attr('name')) {
          $(element).valid();
        }
    
  }

请参阅JSFiddle

不确定这种方法是否有任何警告,并且希望将帖子保持打开状态,以防有人有更好的解决方案。


推荐阅读