3

为什么添加额外的 AngularJS 验证指令会导致$asyncValidators在页面加载时运行多次?

我创建了一个实现 $asyncValidators 的自定义指令。这是该自定义指令的基本结构:

myApp.directive('userSaved',['$q','userLookup',function($q, userLookup){
return {
  restrict: 'A',
  require: 'ngModel',
  link: function(scope, elem, attrs, ctrl){
    ctrl.$asyncValidators.userSaved = function(modelValue, viewValue) {
      // do stuff 
    }
  }
}
}]);

控制器像这样初始化tailNumber模型值:

$scope.tailNumber = 'N33221';

这是user-saved指令在页面加载时运行3 次的 html:

<input ng-model="tailNumber" name="tailNumber"   user-saved 
    ng-minlength="2"   ng-pattern="/^[A-z][a-zA-Z0-9]*$/" >

当我删除时ng-minlength="2",该user-saved指令在页面加载时运行两次(2 次)。这是ng-minlength="2"删除的 html:

<input ng-model="tailNumber" name="tailNumber"   user-saved 
    ng-pattern="/^[A-z][a-zA-Z0-9]*$/" >

当我删除时ng-pattern="/^[A-z][a-zA-Z0-9]*$/",该user-saved指令仅运行1 次。这是删除后的htmlng-pattern="/^[A-z][a-zA-Z0-9]*$/"

<input ng-model="tailNumber" name="tailNumber" user-saved >

为什么我注册的函数$asyncValidators会为附加到表单元素的每个额外的 ng 验证器运行额外的时间?

我的自定义指令是一个昂贵的$http调用,我更喜欢我的自定义指令只在页面加载时运行一次。是否可以使用所有这些 ng 验证器,并且只在页面加载时运行我的异步验证器功能一次而不是 3 次?

4

3 回答 3

4

ngMaxlength这是因为类似的验证指令ngPattern通过调用ngModelController.$validate().

这会导致所有验证指令运行它们的验证逻辑,包括异步验证器。

防止冗余$http调用的一种方法是缓存每个输入的验证结果,实际上这是一种很好的做法。

于 2015-07-31T03:00:30.997 回答
3

实际上,我花了一段时间才弄清楚这一点。如本文所述,Angular 验证器会触发额外的验证。我决定不与这种行为作斗争并解决它,而是回到解析器和格式化程序:

myApp.directive('userSaved',['$q','dataservice',function($q, dataservice){
return {
  restrict: 'A',
  require: 'ngModel',
  link: function(scope, elem, attrs, ctrl){
    ctrl.$parsers.unshift(checkUserSaved);
    ctrl.$formatters.unshift(checkUserSaved);

    function checkUserSaved(value){
        ctrl.$setValidity("usersaved") // the absence of the state parameter sets $pending to true for this validation
        dataservice.getUserSaved(value).then(function(response){
            var userIsSaved = (response === true);

            ctrl.$setValidity("usersaved", userIsSaved); // the presence of the state parameter removes $pending for this validation

            return userIsSaved ? value : undefined;
        });

        return value;
    }
  }
}
}]);

作为参考,您可能还想查看Angular 文档

编辑

经过进一步调查,似乎在 ng-pattern 的情况下,仅当正则表达式从字符串转换时才会触发额外的验证。

直接传递正则表达式:

<div ng-pattern="/^[0-9]$/" user-saved></div> 

在使用验证器管道时为我解决了这个问题。

供参考,请参阅此 github 问题

于 2016-02-29T08:19:24.067 回答
1

我遵循@New Dev 的建议并实现了一个简单的缓存例程,它很好地满足了我的要求,这就是我想出的..

link: function (scope, element, attributes, ngModel) {

        var cache = {};
        ngModel.$asyncValidators.validateValue = function (modelValue) {
            if (modelValue && cache[modelValue] !== true) {
                return MyHttpService.validateValue(modelValue).then(function (resolved) {
                    cache[modelValue] = true; // cache 
                    return resolved;
                }, function(rejected) {
                    cache[modelValue] = false;
                    return $q.reject(rejected);
                });
            } else {
                return $q.resolve("OK");
            }
        };
    }
于 2018-02-20T15:25:48.250 回答