这是一个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 />