asyncValidator依赖于其他字段的值

时间:2015-11-04 08:04:02

标签: angularjs validation

我尝试在其中一个输入中添加验证字段,它应该向服务器请求输入的增值税号是否有效,因此我使用异步验证器。使用此代码可以正常工作:



myApp.factory('isValidVat', function($q, $http) {
  return function(vat) {
    var deferred = $q.defer();
    console.log(vat);
    $http.get('/api/vat/' + vat).then(function() {
      deferred.resolve();
    }, function() {
      deferred.reject();
    });

    return deferred.promise;
  }
});

myApp.directive('validVat', function(isValidVat) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$asyncValidators.vat = isValidVat;
    }
  };
});

<form name="form" novalidate ng-submit="check(form)">
    <div class="vat-field">
        <label>VAT number
            <input type="text" ng-model="formModel.vat" name="vat" valid-vat="true">
        </label>
        <div ng-show="registerForm.$submitted || registerForm.vat.$touched">
            <span ng-show="registerForm.vat.$error.vat">
                <small class="error">Your VAT address is not valid, please correct.</small>
            </span>
        </div>
    </div>
    <div class="country-field">
        <label>Country
            <select ng-model="formModel.country" name="country">
                <option value="{{country.iso_3}}" ng-repeat="country in countries()">{{country.name}}</option>
            </select>
        </label>
    </div>
    <button type="submit">Check</button>
</form>
&#13;
&#13;
&#13;

但是,我想让这个asyncValidator检查条件是另一个字段的值(国家,更具体地说,该国家是否是欧盟国家)。 国家领域是一个组合框,通过一项服务进行推广,该服务记录了所有国家及其大桶信息和欧盟状态。 但是,我不知道如何将所选国家/地区的值注入工厂功能。一个想法是将所选国家/地区链接到它自己的服务并在工厂中使用它,但是当选择另一个国家时,验证不会再次运行。如果选择非欧盟国家,我并不十分关心该领域的情况。

1 个答案:

答案 0 :(得分:3)

将值变为derective很容易,您可以将其传递给相同的属性或其他属性。最好不要使用隔离范围,因为属性指令应该能够处理每个元素。因此,您可以将您的国家/地区信息传递给验证指令,然后将其传递给工厂返回的函数。

另一件事是依赖。验证仅在模型本身更改时运行。所以你必须对它进行观察/观察。

停止说话......代码时间......

以下是基于您的代码的完整工作示例: http://jsbin.com/yuqibajehe/edit?html,js,output

  .factory('isValidVat', function($q, $http, $timeout) {
    return function(vat, country) {
      var deferred = $q.defer();

      console.log(vat, country);

      $timeout(function() {
        if (vat === country) {
          deferred.resolve();
        } 

        deferred.reject();
      },1000);

      return deferred.promise;
    };
  })
    .directive('validVat', function(isValidVat) {
  return {
    restrict: 'A',
    require: 'ngModel',

    link: function(scope, element, attrs, ngModel) {

      attrs.$observe('validVat', function() {
        ngModel.$validate();
      });

      ngModel.$asyncValidators.vat = function(vat) {
        return isValidVat(vat, attrs.validVat);
      };
    }
  };
});

嗨,你可以看到我有点简化异步验证器,但现在已经足够了。 function有两个参数,所以我从其他函数调用它。

指令的用法如下:

 <input type="text" ng-model="vm.vat" name="vat" valid-vat="{{formModel.country}}" />

因此我们将model的值直接传递给属性valid-vat。 在指令中,我们可以将值发送到验证器。

然后我们必须观察验证器的内容并运行验证,如果使用$ validate()更改了它。

对于这种情况,它可能已经足够了,但是如果你想直接传递模型,如:valid-vat =“formModel.country”它将不起作用,因为属性的值不会改变。因此,您可以转到范围,或者更好地评估attr值并观察其更改 - 例如:http://plnkr.co/edit/296x2shAVSe7FRv3mJnp?p=preview