模型更改后切换$ setValidity

Joh*_*ean 5 javascript validation angularjs

我在角创建注册表单有三个输入:email,passwordpasswordConfirm.我的控制器看起来像这样:

app.controller('SignupController', function ($scope, User) {
    $scope.user = {};

    $scope.signup = function() {
        User.save($scope.user, function(success) {
            // TODO
        }, function(error) {
            if (error.status === 422) {
                error.data.errors.forEach(function(item) {
                    $scope.signupForm[item.field].$setValidity(item.error, false);
                });
            }
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

这样做是在用户提交表单进行注册时向我的API发送请求.如果422响应返回(这意味着验证错误),我会遍历它们并根据API返回的内容将相应的输入设置为无效.

我们以已经注册的电子邮件地址为例.我在我的视图中显示验证错误,如下所示:

<small class="error" ng-show="signupForm.email.$error.exists">Email address taken, please use another</small>
Run Code Online (Sandbox Code Playgroud)

这一切都很完美,但我的用户现在卡住了,因为当他们尝试将电子邮件地址更改为另一个时,email字段的有效性不会更改,以允许他们重新提交表单(我根据表单有效性禁用提交按钮) ).

基本上,我需要在用户更改输入模型后exists重置验证属性(在本例中)true.对我来说最好的方法是什么?

编辑:一个小脑波在发布后打了我,我把它添加到我的控制器:

$scope.$watch('user.email', function() {
    // Reset exists validation property back to true
    $scope.signupForm.email.$setValidity('exists', true);
});
Run Code Online (Sandbox Code Playgroud)

这似乎工作.当用户在输入设置为无效后更改模型值时,会将其设置为有效.但这并没有让我觉得这是最好的方法.谁知道更好?

小智 1

我也曾为这个问题苦苦挣扎。阅读您的文章后,我想出了一个可能的解决方案 - 创建一个指令来监视模型的更改并重置更改时的有效性状态(基本上是您建议的内容,但放入通用指令中)

angular.module('app').directive('resetValidityOnChange', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, iElem, iAttrs, ngModelCtrl) {
            ngModelCtrl.$viewChangeListeners.push(function () {
                ngModelCtrl.$setValidity(iAttrs['resetValidityOnChange'], true);
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您必须将此指令添加到要重置的输入中,例如:

<input type="text" ng-model="vm.email" reset-validity-on-change="exists" />
Run Code Online (Sandbox Code Playgroud)