javascript – ngPattern绑定无法正常工作

我想根据select的选择使用ngPattern验证输入.它在第一次选择后起作用,但任何后续选择都无法正确绑定.

这是一个jsfiddle供参考:
http://jsfiddle.net/PLRf5/17/

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js"></script>
    <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
    <style>
        .field-validation-error {
            color: red;
        }
    </style>
</head>
<body>
   <div class="container form-group" ng-app="mod1" ng-controller="ctrl1">
        <p>
            ng-pattern binding is not updating:
            Enter in 'asdf' then click Cuba. ngPattern should update and you should not see "Bad Format".
        </p>

        <div ng-form="genericAddressEntry">
            <div class="form-group" data-ng-class="{ 'has-error': genericAddressEntry.country.$invalid }">
                <label for="country">Country</label>
                <select name="country" class="form-control"
                    data-ng-model="selectedCountry"
                    data-ng-options="country as country.name for country in countries"
                    data-ng-required="true"
                    >
                </select>
            </div>

            <div class="clearFix" ng-bind="selectedCountry | countryToPostalCodeRegex"></div>

            <div class="form-group " data-ng-class="{ 'has-error': genericAddressEntry.postalCode.$invalid }">
                <label for="postalCode">Zip Code</label>

                <input name="postalCode" type="text" class="form-control" data-ng-model="editAddress.postalCode" data-ng-required="selectedCountry.requiresPostal"
                    ng-pattern="selectedCountry | countryToPostalCodeRegex" maxlength="12" />
                <span class="field-validation-error" data-ng-show="genericAddressEntry.postalCode.$error.pattern">Bad Format</span>
                <span class="field-validation-error" data-ng-show="genericAddressEntry.postalCode.$error.required">required</span>
            </div>

        </div>
    </div>

    <script>


        //module:
        angular.module('mod1',[])
          .controller('ctrl1',['$scope',function ($scope) {
           //   $scope.editAddress = { postalCode: "12345" };
              $scope.countries = [
              { name: 'United States',requiresPostal: true,postalRegEx: '^[0-9]{5}([-]?[0-9]{4})?$' },//{ name: 'Canada',postalRegEx: '^[a-yA-Y]\d[a-zA-Z]( )?\d[a-zA-Z]\d$' },{ name: 'Cuba',requiresPostal: false,postalRegEx: undefined }];
              $scope.selectedCountry = $scope.countries[0];
          }])
          .filter('countryToPostalCodeRegex',[function () {
              var allowAllRegex = new RegExp("^.*");
              var escapeRegex = function (str) {
                  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");
              }

              return function (country) {

                  if (!country) {
                      return allowAllRegex;
                  }
                  if (!country.requiresPostal) {
                      return allowAllRegex;
                  }

                  if (!country.postalRegExObj) {
                      country.postalRegExObj = new RegExp(escapeRegex(country.postalRegEx),"i");
                  }
                  return country.postalRegExObj;
              };
          }]);
    </script>

</body>
</html>

解决方法

目前,Angular不会监视仅监视绑定值的更改的属性.还有一些Angular问题在 NgMinlength And NgMaxlength – Set length value dynamically not workinginput does not watch ngPattern value for changes进一步讨论.来自caitp的两个主要评论是:

The general pattern of Angular isn’t to respond to actual changes to
an attribute value,but rather to respond to changes to a bound value.

The thing with this is that currently the pattern doesn’t come from a
parsed expression / scope variable,it’s just a string literal turned
into a regexp,so watching for changes to that means essentially
watching the DOM attribute value for change. I think I mentioned that
on a different issue regarding this a few weeks ago. Watching changes
to the actual DOM attribute is fairly different from what angular is
typically doing.

从这些问题中获取提示,并查看Angular implements ngPattern如何处理这一问题的方法添加一个指令,该指令监视ngPattern属性的Angular eval()以进行更改.如果它看到更改,那么它可以评估ngPattern正则表达式和setValidity.

这使我们可以动态监控属性值.这是指令:

.directive('updatePattern',function() {
    return {
       require: "^ngModel",link: function(scope,element,attrs,ctrl) {
               scope.$watch(function() {
                  // Evaluate the ngPattern attribute against the current scope
                  return  scope.$eval(attrs.ngPattern); 
               },function(newval,oldval) {
                  //Get the value from `ngModel`
                  value = ctrl.$viewValue;

                  // And set validity on the model to true if the element 
                  // is empty  or passes the regex test
                  if (ctrl.$isEmpty(value) || newval.test(value))   {
                     ctrl.$setValidity('pattern',true);
                     return value;
                  } else {
                     ctrl.$setValidity('pattern',false);
                     return undefined;
                 }
              });                                            
            }
        }
    });

我们将新的update-pattern指令添加到html中:

<input name="postalCode" type="text" class="form-control" data-ng-model="editAddress.postalCode" data-ng-required="selectedCountry.requiresPostal"
                    ng-pattern="selectedCountry | countryToPostalCodeRegex" maxlength="12" update-pattern />

working fiddle

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...