我想根据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', requiresPostal: true, 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>
答案 0 :(得分:7)
目前,Angular不监视仅监视绑定值的更改的属性。有几个Angular问题进一步讨论NgMinlength And NgMaxlength - Set length value dynamically not working和input does not watch ngPattern value for changes。 caitp的两个主要评论是:
Angular的一般模式是不回应实际的变化 属性值,而是响应对绑定值的更改。
和
这个问题是目前的模式不是来自a 解析表达式/范围变量,它只是一个字符串文字转 进入正则表达式,所以注意改变这意味着什么 观察DOM属性值以进行更改。我想我提到过 在几个星期前关于这个问题的另一个问题。看着变化 实际的DOM属性与angular是完全不同的 通常在做。
从这些问题中获取提示,并查看Angular implements ngPattern如何处理此问题的方法是添加一个指令,该指令监视eval()
属性的Angular ngPattern
以进行更改。如果它看到更改,则可以评估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 />
答案 1 :(得分:4)
我有一个简单的方法来解决这个问题。
使用pattern
代替ng-pattern
。
如果您有结帐角度源代码,您会发现pattern
和ng-pattern
是相同的指令。
pattern
和ng-pattern
之间有两种不同:
1. 角度会观察到图案的变化。 (那就是我们需要的!)
2. angular将前置^
并将'$'附加到模式
$scope.regex = '\\d\\d'; //angular will convert this to ^\d\d$
$scope.UPPERCASE = '\\D\\D';
HTML:
<input name="test" pattern="regex">
<!-- I can use filter to change my wrong UPPERCASE regex to correct.-->
<input name="test2" pattern="UPPERCASE | lowercase">
答案 2 :(得分:1)
来自@KayadDave的解决方案是完美的,但你可以使用一种解决方法:手动调用$ setViewValue来强制进行ng-pattern评估:
<!-- Add ng-change function -->
<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"
data-ng-change="updatePattern()"
>
</select>
在你的控制器中:
$scope.updatePattern = function() {
var postalCode = $scope.genericAddressEntry.postalCode;
postalCode.$setViewValue(postalCode.$viewValue);
};