更改另一个输入时强制进行 ngPattern 验证

Force ngPattern validation when another input is changed

我有一个 Angular JS 应用程序,其中有一个必需的 phone 数字字段,以及一个国家 select 字段。国家 select 默认为美国。当 selected 国家是美国或加拿大时,我想用国内 phone 号码模式验证 phone 号码字段,但是当任何其他国家是 selected ,我不想验证 phone 号码的模式。

为了完成这个所需的功能,我使用了与 this 类似的解决方案(肮脏的 方式)。我没有检查 requireTel 布尔值,而是检查 countryCodeUSA 还是 CAN 以确定是否使用我的 phone 数字模式进行验证。

此解决方案有效,但前提是您在更改国家/地区后更改 phone 号码。例如,如果您有美国 selected,并输入长国际 phone 号码,例如 +441234567890,它会使用国内 phone 号码验证并显示 Invalid pattern. 但是当我把国家改成Bahamas时,应该不再使用国内的phone号码验证,并且提示Invalid pattern应该离开。但是,在我更改 phone 数字之前,无效模式 消息仍然显示。一旦我更改 phone 号码,消息就会消失。

发生这种情况的原因是当更改国家 select 时,不会再次对 phone 号码字段执行 ng-pattern 验证。有没有办法在国家/地区更改时强制重新评估 ng-pattern 验证?

请参阅下面的代码片段以重现该问题。

var app = angular.module('example', []);

app.controller('exampleCtrl', function($scope) {
  $scope.countries = [{
    countryName: 'United States',
    countryCode: 'USA'
  }, {
    countryName: 'Canada',
    countryCode: 'CAN'
  }, {
    countryName: 'Bahamas',
    countryCode: 'BHS'
  }, {
    countryName: 'Chile',
    countryCode: 'CHL'
  }];

  $scope.selectedCountry = $scope.countries[0];

  $scope.phoneNumberPattern = (function() {
    var regexp = /^\(?(\d{3})\)?[ .\/-]?(\d{3})[ .-]?(\d{4})$/;
    return {
      test: function(value) {
        var countryCode = $scope.selectedCountry.countryCode;
        if (countryCode !== 'USA' && countryCode !== 'CAN') {
          return true;
        }
        return regexp.test(value);
      }
    }
  })();

});
.error {
  color: red;
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="example" ng-controller="exampleCtrl">
  <ng-form name="exampleForm">
    <label>Country:</label>
    <select ng-model="selectedCountry" ng-options="country as country.countryName for country in countries">
    </select>
    <label>Phone:</label>
    <input type="text" ng-model="phone" name="phone" ng-pattern="phoneNumberPattern" required>
    <small class="error" ng-show="exampleForm.phone.$error.pattern">Invalid pattern.</small>
    <small class="error" ng-show="exampleForm.phone.$error.required">Phone number is required.</small>
  </ng-form>
</div>

这是解决该问题的一种方法。

我基本上所做的是在下拉列表中添加 ng-change="changed()"

<select ng-model="selectedCountry" ng-change="changed()" ng-options="country as country.countryName for country in countries">
    </select>

在JS中,我重新设置了输入文本框的值

 $scope.changed=function()
  {
    $scope.phone="";
  }

这将强制再次执行验证。

这是 DEMO .

让我知道此解决方案是否适合您。

这是另一个解决方案。使用 returns 模式的函数。

jsfiddle.

上的实例

angular.module('ExampleApp', [])
  .controller('ExampleController', function($scope) {
    $scope.countries = [{
      countryName: 'United States',
      countryCode: 'USA'
    }, {
      countryName: 'Canada',
      countryCode: 'CAN'
    }, {
      countryName: 'Bahamas',
      countryCode: 'BHS'
    }, {
      countryName: 'Chile',
      countryCode: 'CHL'
    }];

    $scope.selectedCountry = $scope.countries[0];
    var regUSA = /^\(?(\d{3})\)?[ .\/-]?(\d{3})[ .-]?(\d{4})$/;
    var regAll = /.*/;
    $scope.phoneNumberPattern = function() {
      var countryCode = $scope.selectedCountry.countryCode;
      if (countryCode !== 'USA' && countryCode !== 'CAN')
        return regAll;
      else
        return regUSA;
    }
  });
.error {
  color: red;
  font-style: italic;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="ExampleApp">
  <div ng-controller="ExampleController">
    <ng-form name="exampleForm">
      <label>Country:</label>
      <select ng-model="selectedCountry" ng-options="country as country.countryName for country in countries">
      </select>
      <label>Phone:</label>
      <input type="text" ng-model="phone" name="phone" ng-pattern="phoneNumberPattern()" required>
      <small class="error" ng-show="exampleForm.phone.$error.pattern">Invalid pattern.</small>
      <small class="error" ng-show="exampleForm.phone.$error.required">Phone number is required.</small>
    </ng-form>
  </div>
</div>

注意: 在函数外部声明正则表达式变量很重要。如果您尝试按以下方式更改方法:

if (countryCode !== 'USA' && countryCode !== 'CAN')
    return /.*/;
else
    return /^\(?(\d{3})\)?[ .\/-]?(\d{3})[ .-]?(\d{4})$/;

它将导致infinite $digest error