如何在提交后以Angular异步验证表单?

时间:2016-03-23 10:34:36

标签: angularjs forms validation

我有一个验证客户端的注册表格工作正常。我的应用程序还有一个服务器端验证,它为客户端返回一个JSON,每个字段都有错误。

我试着像这样处理它们:

// errors = { 
//    "username": [
//        "Account 'test2@test.com' already exist!"
//    ]
// };

for(var field in errors) {
  $scope.RegForm.$setValidity(field, false);
  $scope.RegForm[field].$error.server = errors[field].join('\n');
}

问题是,即使我改变字段,错误仍然可见。我需要将有效性设置为true,并在某个时刻删除服务器错误。只是不确定如何以及何时。

如何正确处理服务器数据以使其更改? $ asyncValidators不起作用,因为在用户名字段的情况下我不允许注册用户,只是为了查看这样的用户名是否是免费的。

2 个答案:

答案 0 :(得分:0)

试试这个

for (var field in errors) {
    $timeout(function(){
        $scope.RegForm.$setValidity(field, false);
        $scope.RegForm[field].$error.server = errors[field].join('\n');
    });
}

答案 1 :(得分:0)

根据AngularJS - Server side validation and client side forms中建议的响应,我们创建一个指令,在更改模型的属性后重置验证。

jsfiddle上的实例。



angular.module('ExampleApp', ['ngMessages'])
  .controller('ExampleController', function($scope, ServerService) {
    $scope.user = {};

    $scope.doSubmit = function(myForm) {
      ServerService.save().then(function(errors) {
        // Set error from server on our form
        angular.forEach(errors, function(error) {
          myForm[error.fieldName].$setValidity(error.error, false);
        });
      });
    };
  })
  //Simulate Ajax call
  .service('ServerService', function($q, $timeout) {
    var errorsFromServer = [{
      fieldName: "firstName",
      error: "serverError"
    }, {
      fieldName: "lastName",
      error: "serverError"
    }, {
      fieldName: "email",
      error: "serverError"
    }, {
      fieldName: "email",
      error: "serverError2"
    }];
    return {
      save: function() {
        return $q.when(errorsFromServer);
      }
    };
  })
  .directive('serverValidation', function() {
    return {
      restrict: "A",
      require: "ngModel",
      scope: {
        ngModel: "=",
        serverValidation: "=" // String or array of strings with name of errors
      },
      link: function(scope, elem, attr, ngModelCtrl) {
        function setValidity(errorName) {
          console.log(errorName);
          ngModelCtrl.$setValidity(errorName, true);
        }
        if (typeof(scope.serverValidation) == "string") {
          console.log(scope.serverValidation);
          scope.arrServerValidation = [scope.serverValidation];
        } else {
          scope.arrServerValidation = scope.serverValidation;
        }
        var firstError = scope.arrServerValidation[0];
        scope.$watch('ngModel', function() {
          // workaround to don't update $setValidity, then changed value of ngModel
          // update $setValidity, only when server-error is true
          if (firstError && ngModelCtrl.$error[firstError])
            angular.forEach(scope.arrServerValidation, setValidity);
        });
      },
    };
  });

.error {
  color: red;
  font-style: italic;
}

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>

<div ng-app="ExampleApp">
  <div ng-controller="ExampleController">
    <ng-form name="myForm">
      <input ng-model="user.firstName" name="firstName" required server-validation="'serverError'">
      <div ng-messages="myForm.firstName.$error" class="error">
        <div ng-message="required">firstName is required</div>
        <div ng-message="serverError">firstName is server error</div>
      </div>
      <input ng-model="user.lastName" name="lastName" required server-validation="'serverError'">
      <div ng-messages="myForm.lastName.$error" class="error">
        <div ng-message="required">lastName is required</div>
        <div ng-message="serverError">lastName is server error</div>
      </div>
      <input ng-model="user.email" name="email" required server-validation="['serverError','serverError2']">
      <div ng-messages="myForm.email.$error" class="error" multiple="true">
        <div ng-message="required">email is required</div>
        <div ng-message="serverError">email is server error</div>
        <div ng-message="serverError2">email is server error 2</div>
      </div>
      <input ng-disabled="myForm.$invalid" ng-click="doSubmit(myForm)" type="submit">
    </ng-form>
  </div>
</div>
&#13;
&#13;
&#13;