当异步验证器在AngularJS中返回promise时提交表单

时间:2016-04-05 17:50:01

标签: javascript angularjs forms validation

我创建了一个异步验证器'username-validator'来检查用户名可用性并避免远程调用的数量我在'blur'事件而不是'按键'上更新ng-model。因此,验证器仅在“模糊”事件时触发。

<input type="text" ng-model="signup.username" name="username"
  required 
  username-validator 
  ng-model-options="{ updateOn: 'blur' }">

但是当表单被提交时,它会检查表单是否有效,然后才会提交。

$scope.submit = function(form) {
  if (form.$valid) {
    alert('submitting', $scope.signup.username, $scope.signup.password);
  }
};

但是当我单击“提交”按钮并且表单处于$ pending状态时,表单不会一次性提交,因为在单击时它处于$ pending状态且$ valid未定义。

我想编写$ scope.submit函数来处理一旦$ pending状态被解决后的提交。

我该怎么做?

不要为$ pending状态禁用“提交”按钮。

为了演示问题,我正在添加运行代码段。

angular.module('app', ['ngMessages'])
  .controller('MainCtrl', function($scope) {
    $scope.signup = {};
    $scope.submit = function(form) {
      if (form.$valid) {

        alert('submitting ' +  $scope.signup.username + ' ' + $scope.signup.password);
      }

    };
  })
  .directive('usernameValidator', function($q, $timeout) {
    return {
      require: 'ngModel',
      link: function(scope, element, attrs, ngModel) {
        ngModel.$asyncValidators.username = function(modelValue, viewValue) {
          if (!viewValue) {
            return $q.when(true);
          }
          var deferred = $q.defer();
          $timeout(function() {
            // Faking actual server-side validity check with $http.
            // Let's pretend our service is so popular all short username are already taken
            if (viewValue && viewValue.length < 5) {
              deferred.reject();
            }

            deferred.resolve();
          }, 2000);
          return deferred.promise;
        };
      }
    };
  });
.validation-error {
  color: red;
}
.validation-pending {
  color: orange;
}
<!DOCTYPE html>
<html>

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

  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body ng-app="app">
  <div ng-controller="MainCtrl">
    <form name="myForm" ng-submit="submit(myForm)" novalidate>
      <div>
        <label>
          Username:
          <input type="text" ng-model="signup.username" name="username" required username-validator ng-model-options="{ updateOn: 'blur' }">
        </label>
        <div ng-if="myForm.username.$dirty">
          <div ng-messages="myForm.username.$error" class="validation-error">
            <div ng-message="required">Username required</div>
            <div ng-message="username">Username already in use</div>
          </div>
          <div ng-messages="myForm.username.$pending" class="validation-pending">
            <div ng-message="username">Checking username availability...</div>
          </div>
        </div>
      </div>
      <div>
        <label>
          Password:
          <input type="password" ng-model="signup.password" name="password" required>
        </label>
        <div ng-messages="myForm.password.$error" ng-if="myForm.password.$dirty" class="validation-error">
          <div ng-message="required">Password required</div>
        </div>
      </div>
      <button type="submit">Submit</button>
    </form>
  </div>
</body>

</html>

1 个答案:

答案 0 :(得分:0)

您可以在检查用户名

时将承诺附加到范围
scope.usernameCheck = deferred.promise;
return deferred.promise;

然后在你的提交功能中等待承诺得到解决

$scope.submit = function(form) {
    if ($scope.usernameCheck) {
        $scope.usernameCheck.then(function() {
            if (form.$valid) {
                alert('submitting ' +  $scope.signup.username + ' ' + $scope.signup.password);
            }
        });
    }
};