自定义验证指令覆盖其他验证

Custom validation directive overrides other validations

本文关键字:验证 其他 覆盖 指令 自定义      更新时间:2023-09-26

我已经创建了一个自定义验证,用于验证用户是否存在。如果用户不存在,则必须验证此验证。它是一个返回JSON内容的简单GET查询。

问题是这个验证似乎覆盖了其他验证。如果用户,但小于3个字符,通常不应该验证字段,但它是!如果我删除我创建的自定义验证,问题就会消失,长度验证就会工作。

下面是我的代码:

angular.module('userRegistrationApp').directive('usernameNotExist', function($http) {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
            ctrl.$parsers.unshift(function(viewValue){
                var user = viewValue;
                $http({method: 'GET', url: '/register/doesUserOrEmailExist/' + user }).
                    success(function(data, status, headers, config) {
                       if(data.doesUserOrEmailExist == false) {
                            ctrl.$setValidity('usernameNotExist', true);
                            return viewValue;
                        }else {
                            ctrl.$setValidity('usernameNotExist', false);
                            return undefined
                        }
                    }).error(function(data, status, headers, config) {
                        ctrl.$setValidity('usernameNotExist', false);
                        return undefined;
                    })
            });
        }
    }
});
<input type="text" id="sonata_user_registration_form_username" name="sonata_user_registration_form[username]" required="required" maxlength="255" pattern=".{2,}" class="form-control" username-not-exist="" ng-minlength="3" ng-focus="setFocus('username')" ng-model="userRegistrationService.username">

我完全按照他们在文档中所说的去做,但是我得到了这个错误!

我想我已经找到解决办法了。它的灵感来自这个答案:https://stackoverflow.com/a/12865401/2573319

试试下面的指令,看看它是否适合你!

angular.module('userRegistrationApp').directive('usernameNotExist', function($http) {
    var timeout;
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
                scope.$watch(attrs.ngModel, function(value) {
                    var user = value;
                    // if there was a previous attempt, stop it.
                    if(timeout)
                        clearTimeout(timeout);
                    // start a new attempt with a delay to keep it from
                    // getting too "chatty".
                    timeout = setTimeout(function(){
                        // call to some API that returns { isValid: true } or { isValid: false }
                        $http({method: 'GET', url: '/register/doesUserOrEmailExist/' + user }).success(function(data) {
                            if(data.doesUserOrEmailExist == false) {
                                ctrl.$setValidity('usernameNotExist', true);
                            }
                            else {
                                ctrl.$setValidity('usernameNotExist', false);
                            }
                        }).error(function(data) {
                            ctrl.$setValidity('usernameNotExist', false);
                        });
                    }, 200);
                })
        }
    }
});

我有同样的问题,发现解决方案是使用

scope.$watch

不是

ctrl.$parsers.unshift

在我看来,ctrl.$parsers.unshift将使您的自定义验证在其他验证之前执行,然后如果您的自定义验证失败,return undefined;将将模型值设置为未定义,以便其他验证将没有有效值来处理。

scope.$watch将在所有其他验证通过后触发您的自定义验证。

我还没有在angular文档中找到支持这个的东西,这是基于我的调试经验。