【问题标题】:ngModel.$setValidity only works oncengModel.$setValidity 只工作一次
【发布时间】:2017-02-03 16:52:06
【问题描述】:

我目前正在处理 angular bootstrap ui datepicker popup 验证,问题是我可以设置最大最小日期并验证(仅当用户通过单击日历设置日期时),但是当用户手写日期那些验证没用,我为此做了一个指令,但只验证并设置一次错误,这是我的标记

<div class="form-group clearfix">
  <div class="col-md-3 m-t-b-20">
    <label>Date validation</label>
    <p class="input-group col-md-12">

      <input id="validationDate"
             type="text"
             name="validationDate"
             class="form-control"
             uib-datepicker-popup="{{ Ctrl.format }}"
             data-ng-model="Ctrl.formObj.validationDate"
             is-open="Ctrl.validationDate.opened"
             datepicker-options="Ctrl.dateOptions"
             ng-required="true"
             close-text="Close"
             placeholder="Fecha de radicacion"
             ng-click="Ctrl.openDatePicker('validationDate')"
             required
             date-validate/>

      <span class="input-group-btn">
        <button type="button"
                class="btn btn-default"
                ng-click="Ctrl.openDatePicker('validationDate')"
                data-ng-disabled="Ctrl.blockFields">
          <i class="glyphicon glyphicon-calendar"></i>
        </button>
      </span>

    </p>

    <!-- THE ERROR TO SHOW -->
    <p data-ng-show="stepOne.validationDate.$error.validbound"
       class="text-red">
      the selected date exeeds the max and min date boundaries
    </p>
  </div>

这是我的指令

var dateValidate = function () {
    return {
      require: 'ngModel',
      link: function (scope, elem, attr, ngModel) {

        elem.bind('keyup', function(value) {

            var atrvls = scope.$eval(attr.datepickerOptions),
                maxDate = moment(atrvls.maxDate, 'DD/MM/YYYY'),
                minDate = moment(atrvls.minDate, 'DD/MM/YYYY'),
                cDate = moment(elem.val(), 'DD/MM/YYYY', true);

            ngModel.$setValidity('validbound', true);

            if (!cDate.isValid()) {
                return false;
            }

            if (!cDate.isBetween(minDate, maxDate)) {
                ngModel.$setValidity('validbound', false);
            }

        });

    }
};

};

我想知道为什么只进行第一次验证,然后指令什么都不做

【问题讨论】:

    标签: angularjs twitter-bootstrap validation angularjs-directive datepicker


    【解决方案1】:

    这里有几件事。

    首先,Moment 的isBetween() 中给出的日期是不包含日期的,而datePickerminDatemaxDate 是包含日期的。因此,您需要传递其他参数以将这些最小和最大日期包含在该范围内:

    cDate.isBetween(minDate, maxDate, null, '[]')
    

    其次,如果您正在寻找有关日期是否在范围内的即时反馈,那么您需要将 $setValidity 包装在 scope.$apply 函数中。

    如果不查看 Datepicker 弹出窗口的 javascript,我无法确切说明为什么需要这样做,但从实验中我可以看到它仅在弹出窗口关闭时应用 ng-invalid-validbound 属性(而应用 ng-valid-validbound一旦有效性设置为真)。我认为这是提高性能的方式,因为无论如何您都无法使用弹出窗口选择越界日期,您只能采用另一种方式 - 从无效日期到使用弹出窗口选择有效日期。

    这或多或少是我的做法:

    var dateValidate = function() {
      return {
        require: 'ngModel',
        link: function(scope, elem, attr, ngModel) {
          elem.bind('keyup', function(value) {
    
            var atrvls = scope.$eval(attr.datepickerOptions),
              maxDate = moment(atrvls.maxDate, 'DD/MM/YYYY'),
              minDate = moment(atrvls.minDate, 'DD/MM/YYYY'),
              cDate = moment(elem.val(), 'DD/MM/YYYY', true);
    
            if (!cDate.isValid()) {
              scope.$apply(ngModel.$setValidity('validbound', null));
              return false;
            }
    
            if (!cDate.isBetween(minDate, maxDate, null, '[]')) {
              scope.$apply(ngModel.$setValidity('validbound', false));
            } else {
              scope.$apply(ngModel.$setValidity('validbound', true));
            }
    
          });
        }
      };
    };
    

    这是一个笨蛋:http://plnkr.co/edit/toXpEWNa99o7Gfs69KfZ?p=preview

    【讨论】:

    • nop,嗯...是的...但我忘了提到它是用 angular 1.6.1 制作的,我在 plnker 上更改了它,当您手动输入日期时不起作用
    • 我不确定你的意思?我已将 plunk 更新为 1.6.1,对我来说,输入日期 15/02/2017 显示为绿色(在范围内),输入 25/02/2017 显示为红色(超出范围)。我正在使用 Firefox,虽然我不希望它依赖于浏览器
    • 也使用 firefox,如果我输入“12/12/2018”,输入变为红色,如果我删除最后一个字符,它变为正常,这就是我正在搜索的预期行为,但如果之后我再次输入“12/12/2016”(在范围内)输入变为红色
    • "12/12/2016" 不在范围内,这就是它变红的原因。我设置的范围是 04/02/2017 到 22/02/2017
    • 否则,如果您希望边框在范围内保持正常颜色,并且仅在不显示红色时显示红色,则删除 Plunk 中的#validationDate.ng-valid-validbound绿色边框 CSS 规则
    【解决方案2】:

    在链接函数中 - 使用您的自定义验证创建一个验证函数,您可以在 ngModel.$viewValue 上添加 $watch

    scope.$watch(function () {
                 return ngModel.$viewValue;
             }, validate);
    

    我认为“模糊”会更好,而不是“Keyup”。

    【讨论】:

    • 好的,这是一个选项,但我仍然不明白为什么第一次验证后验证失败
    猜你喜欢
    • 2017-01-06
    • 2018-06-22
    • 2015-09-18
    • 2013-12-31
    • 1970-01-01
    • 2013-09-28
    • 2013-03-30
    • 2015-06-04
    • 2019-05-18
    相关资源
    最近更新 更多