使用AngularJS进行异步验证

3

有几个问题出现了。首先,我该如何在模板中捕获错误,因为即使响应是404并且正确的代码被执行,has-error类也不会被应用。

其次,这只在第一次有效。如果我离开该字段然后再次输入,每次按键时都会出现 TypeError: validator is not a function 异常(正如您在代码中所看到的,我仅在 blur 上执行此操作)。我做错了什么?

服务调用

this.CheckIfUnique = function(code) {
    var deferred = $q.defer();
    $http.get("/Api/Codes/Unique/" + code).then(function() {
            deferred.resolve();
        }, function() {
            deferred.reject();
        });
        return deferred.promise;
    };

该指令

var uniqueCode = [ "CodeService", function(codeService) {
    return {
        restrict: "A",
        require: "ngModel",
        link: function(scope, element, attrs, ctrl) {
            element.bind("blur", function(e) {
                if (!ctrl || !element.val()) return;
                var currentValue = element.val();
                ctrl.$asyncValidators.uniqueCode = codeService.CheckIfUnique (currentValue);
            });
        }
    };
}];
codeModule.directive("uniqueCode",uniqueCode);

The HTML

<div class="form-group" ng-class="{'has-error' : ( codeForm.submitted && codeForm.code.$invalid ) || ( codeForm.code.$touched && codeForm.code.$invalid ) }">
    <label class="col-md-4 control-label" for="code">Code</label>
    <div class="col-md-8">
        <input class="form-control" id="code" name="code" ng-model="newCode.code" ng-required="true" type="text" unique-code />
        <span class="help-block" ng-show="( codeForm.submitted && codeForm.code.$error.required ) || ( codeForm.code.$touched && codeForm.code.$error.required)">Please enter a code</span>
        <span class="help-block" ng-show="codeForm.code.$pending.code">Checking if the code is available</span>
        <span class="help-block" ng-show="( codeForm.submitted && codeForm.code.$error.uniqueCode ) || ( codeForm.code.$touched && codeForm.code.$error.uniqueCode)">This code already exist</span>
    </div>
</div>

MVC 控制器

public async Task<ActionResult> Unique(string code)
{
    if (string.IsNullOrWhiteSpace(code))
    {
        return new HttpStatusCodeResult(HttpStatusCode.NotFound);
    }
    return _db.Codes.Any(x => x.Code = code)
        ? new HttpStatusCodeResult(HttpStatusCode.NotFound)
        : new HttpStatusCodeResult(HttpStatusCode.Accepted);
}

编辑:

为了澄清,API仅在我离开字段时调用,异常在按键时抛出(仅在第一次离开字段后)。

编辑2:

如果有人错过了评论,dfsq的答案有效,如果您在输入框中添加ng-model-options="{ updateOn: 'blur' }",它将仅在blur上验证。


你的服务调用中,resolve() 的调用应该放在成功回调函数中而不是失败回调函数中吗? - Mourndark
应该是我的错 :) 我已经卡在这里有一段时间了,可能在某个时候切换了它们。但这仍然无法解决问题。我编辑了 Q。 - GregoryHouseMD
1
在您的标记中也应该是 codeForm.$submitted ;-) - Mourndark
刚刚看到已经实现了,所以我将其添加到需要进行的更改列表中。 - GregoryHouseMD
除此之外,假设您从服务器获取了正确的数据,我不知道该提出什么建议。如果在服务调用或link上设置断点,您应该能够在验证发生的时候(至少在Chrome中)看到DOM的快照,包括动态表单类,这可能有助于诊断它。 - Mourndark
请参考dfsq的答案 :) - GregoryHouseMD
2个回答

1
您没有提供正确的验证器函数。它应该使用返回承诺对象(来自您的服务)的匿名函数。您也不需要模糊事件:
var uniqueCode = ["CodeService", function(codeService) {
    return {
        restrict: "A",
        require: "ngModel",
        link: function(scope, element, attrs, ctrl) {            
            ctrl.$asyncValidators.uniqueCode = function(value) {
                return codeService.CheckIfUnique(value);
            };
        }
    };
}];
codeModule.directive("uniqueCode", uniqueCode);

另外,您应该清理服务方法,以避免使用冗余的延迟对象:
this.CheckIfUnique = function(code) {
    return $http.get("/Api/Codes/Unique/" + code);
};

这解决了问题,谢谢,但我仍需要blur事件,因为在我开始输入新代码后,我会在每次按键时调用API。 - GregoryHouseMD
而且,因为这是一个两部分的问题,那么验证信息呢?它仍然没有显示。 - GregoryHouseMD
使用ng-model-options="{ updateOn: 'blur' }"修复了模糊问题。 - GregoryHouseMD

0
关于你问题的另一部分,消息没有显示出来的原因是: 对于"Checking the code"消息,你使用了codeForm.code.$pending.code,而应该使用codeForm.code.$pending.uniqueCode 这里是正常工作的plunker链接: http://plnkr.co/edit/FH8GBhOipgvvUzrFYlwx?p=preview

刚刚注意到这个问题,我正准备在这里发布它。 - GregoryHouseMD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接