AngularJS - 为什么在其他验证器失败时不调用异步验证器?

时间:2015-07-17 12:58:37

标签: angularjs validation asynchronous angularjs-directive

不是我不喜欢或不喜欢,但问题是同步验证器的行为有所不同。即使其他验证器之前失败,也始终会调用它们。因此,验证器中存在不均匀的行为,这也会导致一些问题。

我用一个简单的程序测试了所有这些。

我创建了一个同步验证器和一个验证完全相同的异步验证器。 在两个验证器中,我以“典型”方式提交错误:

ctrl.$validators.sync= function(modelValue,viewValue){...

我还提交了一个额外的错误(例如告诉异步验证中存在连接问题):

ctrl.$setValidity('syncplus',...

此外,除了不均匀的行为之外,额外的验证错误还会导致异步验证器中的其他问题:

正如我所看到的,如果输入被修改,异步“典型”验证总是立即重置。 (我不知道在哪里) 但是额外的验证器永远不会重置。并且,由于当其他验证器失败时未调用异步验证器,我无法更新其他验证器,因此仍然会显示之前的错误,即使它可以是有效输入。

try my program in plunker

在这里你可以看到验证器的js代码:

angular.module('app',[])
.directive('async', function($q,$timeout){
    return{
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl){

            var nono_username= ['a','aa','aaa','aaaaa']; // SHOULD FAIL from 1 to 5 a's, BUT NOT with 4 a's

            ctrl.$asyncValidators.async= function(modelValue,viewValue){

                scope.data.called+= 'A'; // This way we know Async has been called
                var def= $q.defer();

                $timeout(function() { // Mock a delayed response
                    if(nono_username.indexOf(modelValue)===-1){ // The username is available
                        ctrl.$setValidity('asyncplus',true);
                        def.resolve();
                    } else {
                        ctrl.$setValidity('asyncplus',false);
                        def.reject();
                    }
                }, 200);

                return def.promise;
            };
        }
    };
})
.directive('sync', function($q){
    return{
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl){

            var nono_username= ['a','aa','aaa','aaaaa']; // SHOULD FAIL from 1 to 5 a's, BUT NOT with 4 a's

            ctrl.$validators.sync= function(modelValue,viewValue){
                scope.data.called+= 'S'; // This way we know Sync has been called
                ctrl.$setValidity('syncplus',nono_username.indexOf(modelValue)===-1);
                return nono_username.indexOf(modelValue)===-1;
            };
        }
    };
})
/* Maybe a solution for resetting asyncplus?
.directive('asyncplus', function($q){
    return{
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl){
            ctrl.$validators.asyncplus= function(modelValue,viewValue){
                return true;
            };
        }
    };
})
*/
.controller('Controller',['$scope',function($scope){
    $scope.data= {username:'',called:''};
}]);

结论:

  • 为什么在其他验证器时不调用异步验证器 失败?
  • 为什么不重置额外的$ setValidity验证器?
  • 我可以用简单的方式重置所有验证器吗? (我发现创造了一个 具有相同名称的同步验证器并包含指令 输入解决了它,正如我在上面的注释代码中所述)
  • 您认为避免所有这些问题的最佳选择是什么? 我应该使用哪种解决方法?

1 个答案:

答案 0 :(得分:0)

如果你想让它像这样工作,你可以使用$ parsers和$ formatters:

.directive('async', function($q,$timeout){
    return{
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl){

            var nono_username= ['a','aa','aaa','aaaaa']; // SHOULD FAIL from 1 to 5 a's, BUT NOT with 4 a's

            var validate = function(value) {

                $timeout(function() { // Mock a delayed response
                    if(nono_username.indexOf(value)===-1){ // The username is available
                        ctrl.$setValidity('asyncplus',true);
                    } else {
                        ctrl.$setValidity('asyncplus',false);
                    }
                }, 200);

                return value;
            };

            ctrl.$parsers.push(validate);
            ctrl.$formatters.push(validate);
        }
    };
})
相关问题