【问题标题】:ngModel updated after ngBlurngBlur 后更新的 ngModel
【发布时间】:2016-05-04 23:16:25
【问题描述】:

我在 AngularJS 中使用 ui-bootstrap 的 datepicker 输入。它有一个 ngModel 和一个绑定到 ngBlur 事件的验证方法:

<input id="startDate" type="text" ng-model="myCtrl.startDate" ng-blur="myCtrl.validateDate()"/>

验证方法根据控制器中的一组规则检查 ngModel,并在需要时发出警报。这是控制器的相关部分:

var vm = this;
vm.startDate = new Date();
vm.minStartDate = new Date(2000,1,1);
vm.validateDate = function(){
    if(vm.startDate < vm.minStartDate)
        alert("Start date can't be earliar than 2000");
}

问题在于,验证方法在模型更新之前运行。示例场景如下:

规则:startDate 不能早于 2000 年。 当页面加载时,startDate 值最初设置为今天。用户从日历中选择 31.12.1999,调用 ngBlur 方法。但是,ngModel 尚未更新。因此,验证检查今天的值并说确定。实际上,它应该使用 31.12.1999 检查 ngModel 的值。该值在输入视图上同时更改,但在后台,它是在触发模糊方法后设置的。据我所知,AngularJS 中的双向绑定通常用于此目的,但 ngBlur 必须是一个例外。

我尝试了很多东西,例如;

  • 向组件添加 ng-model-options:

    ng-model-options="{ updateOn: 'blur' }"

  • 通过修改输入元素使用前置和后置链接

  • 使用 ng-change 代替 ng-blur

但是,上述方法都不起作用,并且在模型更新之前仍然会运行 ng-blur。

【问题讨论】:

    标签: angularjs angular-ui-bootstrap angular-ngmodel onblur


    【解决方案1】:

    我通过手动更新控制器内部的值找到了解决方案。显然,AngularJS 不会使用 HMTL 元素内的值更新模型,直到触发 blur 事件。所以,最好写一个方法来更新它。

    我可以按如下方式访问元素内部的值:

    vm.startDate = angular.element('#startDate').val();
    

    然后我可以用一个方法来包装它:

    vm.updateModels() = function(){
        vm.startDate = angular.element('#startDate').val();
    }
    

    最后,我只是在我的模糊事件的第一个调用它:

    vm.validateDate = function(){
        //Update first
        vm.updateModels();
        //Then validate
        if(vm.startDate < vm.minStartDate)
            alert("Start date can't be earliar than 2000");
    }
    

    Ta tammm,现在我可以验证更新值了!

    【讨论】:

      【解决方案2】:

      确保验证仅在值更新后触发的一种简单方法是在 ng-change 而不是 ng-blur 上调用它。这样您就可以确保控制器仅在 ng-model 值更新后进行评估。

      【讨论】:

        【解决方案3】:

        尝试构建您自己的自定义验证器(指令)

        app.directive('integer', function() {
          return {
            require: 'ngModel',
            link: function(scope, elm, attrs, ctrl) {
              ctrl.$validators.integer = function(modelValue, viewValue) {
                if (ctrl.$isEmpty(modelValue)) {
                  // consider empty models to be valid
                  return true;
                }
        
                if (INTEGER_REGEXP.test(viewValue)) {
                  // it is valid
                  return true;
                }
        
                // it is invalid
                return false;
              };
            }
          };
        });
        

        检查这个例子 https://plnkr.co/edit/SZoBKakhzIq5wRoCvEyG?p=preview

        【讨论】:

          猜你喜欢
          • 2014-11-21
          • 1970-01-01
          • 2017-03-14
          • 1970-01-01
          • 2020-02-27
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多