这是一个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>
解决方法
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 />