【问题标题】:Validate date field on focusout with jquery-validation使用 jquery-validation 验证焦点输出的日期字段
【发布时间】:2018-06-29 16:00:20
【问题描述】:

日期输入字段无效,第一次选择日期时。
它显示必需的错误消息,因为字段有一个空值(检查控制台日志)。但该字段将在第二次更改时有效。

注意:一个原因是日期输入字段在选择日期时失去焦点(点击事件)。但是只有在点击事件发生时才会填充日期。但是验证器将验证焦点事件的字段。

我正在使用Jquery Validation 验证表单,使用bootstrap-datepicker 作为小部件。

^^for Better UX Run code sn-p on full-page ;) 要么 jsfiddle

来自@Sparky / @Vignesh 回答:是的,这是一种解决方法,我们可以使用 change/hide/changeDate(module attribute) 事件处理程序。一旦设置了输入值,它就会被触发。 但问题是,每当我们从年->月->日期中选择时,每次点击选择器时,都会从输入中移除焦点,并触发 focusout 事件并显示错误消息,直到选择日期。

它不像选择字段那样平坦。在选择字段中,在从字段小部件中选择选项之前不会触发焦点事件。像这样,我们如何在不看到错误消息的情况下移动年/月/日选项?。

jQuery: & HTML

    $(function() {
      $("#editEventForm").validate({
        rules: {
          full_name: {
            required: true,
          },
          event_date: {
            required: true,
          },
        },
        messages: {
          full_name: "Please enter your full name!",
          event_date: "Please enter valid date!",
        },
        highlight: function(element, errorClass) {
          var e = $(element);
          e.closest('.has-feedback').removeClass('has-success').addClass('has-error');
        },
        unhighlight: function(element, errorClass) {
          var e = $(element);
          e.closest('.has-feedback').removeClass('has-error').addClass('has-success');
        },
        onfocusout: function(element) {
          console.log("element value --> ", $(element).val());
          return $(element).valid();
        },
      });
      $('#eventDate').datepicker({
        autoclose: true,
      }).on('change', function() {
        $(this).valid(); // triggers a validation test
        // $(this) refers to $('#eventDate')
      });

    });
.has-error :focus {
  border-color: #f84545 !important;
}
.error {
  color: #f84545;
}
<link id="bs-css" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<link id="bsdp-css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.17.0/dist/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/js/bootstrap-datepicker.min.js"></script>



<form id="editEventForm">
  <div class="form-group">
    <div class="has-feedback">
      <label for="eventDate">Full Name * </label>
      <input class="form-control" id="fullName" name="full_name" type="text">
    </div>
    <div class="has-feedback">
      <label for="eventDate">Event Date * </label>
      <input class="form-control" id="eventDate" name="event_date" placeholder="MM/DD/YYYY" type="text">
    </div>
  </div>
  <input type="submit" value="ClickMe">
</form>

【问题讨论】:

  • @Sparky 是的,我已经完成了。但是我们怎样才能在不触发错误消息的情况下移动年/月/日选项呢?
  • @ramganesh 更新了我的答案。请看一下。

标签: javascript jquery-validate bootstrap-datepicker


【解决方案1】:

TL;DR :点击事件将焦点移动到被点击的元素。因此,在选择器中单击日期时,会从输入中移除焦点并触发 focusout 事件。在设置输入值之前,选择器会执行各种操作。因此,focusout 上的值保持为空。因此,警报仍保留在 UI 中。

解释:点击/聚焦date 字段时,datepicker 打开。当您单击datepicker 中的date 时,就会出现真正的问题。单击它后,您可以看到日期字段立即失去焦点(闪烁的插入符号消失)。当我们配置autoclose:true 时,选择器会立即关闭。以下是日期选择器中编写的隐藏功能。

hide: function() {
        return this.isInline || !this.picker.is(":visible") ? this : (this.focusDate = null,
        this.picker.hide().detach(),
        this._detachSecondaryEvents(),
        this.setViewMode(this.o.startView),
        this.o.forceParse && this.inputField.val() && this.setValue(),
        this._trigger("hide"),
        this)
  1. 使选择器隐藏。
  2. detach() 使关联的元素被移除,保持元素细节不变,以防再次重新插入元素。
  3. 从日期选择器中删除附加的辅助事件。
  4. 将视图模式设置为配置的模式(因为在我们的问题中没有配置,它设置为默认模式)。
  5. 解析选中的值,并将解析结果设置到输入框。
  6. 运行选项中配置的自定义回调(如果有)

所以在设置输入值之前,onfocusout 事件会被触发。并且由于当时不存在任何值,因此会显示错误。

为防止这种情况发生,请在选择器中添加一个hide 事件处理程序(如下所示),并从那里处理相同的验证。一旦设置了输入值(如上所述),就会触发此自定义事件处理程序。

$(function() {
  $("#editEventForm").validate({
    rules: {
      full_name: {
        required: true,
      },
      event_date: {
        required: true,
      },
    },
    messages: {
      full_name: "Please enter your full name!",
      event_date: "Please enter valid date!",
    },
    onfocusout: function(element) {
        $(element).valid();
    },
  });
  $('#eventDate').datepicker({
    autoclose: true,
    orientation: "bottom right"
  }).on("hide",function(){
      $("#editEventForm").data("validator").settings.ignore="";
      $(this).valid();
  }).on("focus",function(){
      $("#editEventForm").data("validator").settings.ignore="#eventDate, :hidden";
  });
});
<link id="bs-css" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<link id="bsdp-css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.17.0/dist/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/js/bootstrap-datepicker.min.js"></script>



<form id="editEventForm">
  <div class="form-group">
    <div>
      <label for="eventDate">Full Name * </label>
      <input class="form-control" id="fullName" name="full_name" type="text">
    </div>
    <div>
      <label for="eventDate">Event Date * </label>
      <input class="form-control" id="eventDate" name="event_date" placeholder="MM/DD/YYYY" type="text">
    </div>
  </div>
  <input type="submit" value="ClickMe">
</form>

编辑:如前所述,我们无法阻止focusout 事件触发。但是可以通过变通方法来满足要求。

在焦点上,ignore 验证和hide,删除忽略的验证并验证。

为了清楚起见,忽略通过

对指定元素的验证
$("#editEventForm").data("validator").settings.ignore="#eventDate, :hidden";`

:hidden 是默认值,所以不要省略)。在验证期间,插件在内部使用 jQuery not 选择器来忽略元素。在隐藏日期选择器时(通过选择日期/点击外部),从配置中删除元素并应用验证。

【讨论】:

  • @ramganesh 更新了答案。希望对您有所帮助。
  • :) 是的,它按预期工作正常,我只是简化了你的东西。看我的回答。
【解决方案2】:

由于赏金问题,问题不能是closed as duplicate

jQuery Validate 插件会自动触发对普通表单输入字段的聚焦和键控的验证测试,并且不适用于日期选择器。

无论何时选择日期,您都必须以编程方式触发验证:

$('#eventDate').datepicker({
    autoclose: true,
    // endDate: '+45d', // show current date - next 45 days
}).on('change', function() {
    $(this).valid();  // triggers a validation test
    // $(this) refers to $('#eventDate')
});

【讨论】:

    【解决方案3】:

    简化@Vignesh 解决方法。

    我们可以跳过onfocusout的字段验证,我们在hide事件上进行验证

    // here we can skip the validation
    onfocusout: function(element) {
      var elementId = element.getAttribute('id');
      if (elementId === "eventDate") {
        // datepicker widget - don't do validation on focusout event
        return false;
      }
      return $(element).valid();
    },
    
    
    // here we can do the validation
    $('#eventDate').datepicker({
      autoclose: true,
    }).on('hide', function() {
      // datepicker - on hide do the field validation
      $('#eventDate').valid();
    });
    

    Jsfiddle

    【讨论】:

    • 是的..也可以这样做....但是我想公开在内部执行相同操作的方法,您应该知道它对谁有帮助。
    【解决方案4】:

    您可以在日期选择器中设置首次加载日期。

    $('#eventDate').datepicker({
                    autoclose: true 
                }).datepicker("setDate", 'now');
    

    【讨论】:

    • 它用于将今天的日期设置为默认日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多