Javascript 模式绑定不起作用

Javascript 模式绑定不起作用,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我想使用基于select选择的ngPattern验证输入。它在第一次选择之后工作,但任何后续选择都不能正确绑定 这里有一个JSFIDLE供参考: .字段验证错误{ 颜色:红色; } ng模式绑定未更新: 输入“asdf”,然后单击Cuba。ngPattern应该更新,您不应该看到“坏格式”。 国家 邮政编码 格式错误 要求的 //模块: 角度。模块('mod1',[]) .controller('ctrl1',['$scope',函数($scope){ //$scope.editAddr

我想使用基于select选择的ngPattern验证输入。它在第一次选择之后工作,但任何后续选择都不能正确绑定

这里有一个JSFIDLE供参考:


.字段验证错误{
颜色:红色;
}

ng模式绑定未更新:
输入“asdf”,然后单击Cuba。ngPattern应该更新,您不应该看到“坏格式”。

国家 邮政编码 格式错误 要求的 //模块: 角度。模块('mod1',[]) .controller('ctrl1',['$scope',函数($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',requirePostal:false,postalRegEx:undefined}]; $scope.selectedCountry=$scope.countries[0]; }]) .filter('countryToPostalCodeRegex',[函数(){ var allowAllRegex=新的RegExp(“^.*”); var escapeRegex=函数(str){ 返回str.replace(/[\-\[\]\/\{\\}(\)\*\+\?\.\\\^\$\\\\\\\\\\;]/g,“\$&”); } 返回函数(国家/地区){ 如果(!国家){ 返回Allowallegex; } 如果(!country.requirePostal){ 返回Allowallegex; } 如果(!country.postalRegExObj){ country.postalRegExObj=新的RegExp(escapeRegex(country.postalRegEx),“i”); } 返回国家/地区。postalRegExObj; }; }]);
当前Angular不监视属性的更改,它只监视绑定值。有几个角度的问题需要进一步讨论。caitp的两个关键意见是:

角度的一般模式是不响应实际的变化 属性值,而是响应对绑定值的更改

这样做的问题是,当前的模式不是来自 解析表达式/范围变量,它只是一个字符串文本 进入一个regexp,因此观察对它的更改本质上意味着 观察DOM属性值的变化。我想我提到过 几周前关于这个的另一个问题。观察变化 对于实际的DOM属性,它与角度是完全不同的 通常是这样

从这些问题中得到一个线索,看看如何处理这个问题的一种方法是添加一个指令,用于监视
ngPattern
属性的Angular
eval()
。如果它看到变化,那么它可以评估
ngPattern
regex和
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;
                 }
              });                                            
            }
        }
    });
我们将新的
更新模式
指令添加到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 />


来自@KayadDave的解决方案是一个完美的解决方案,但您可以使用一个变通方法:手动调用$setViewValue以强制ng模式评估:

<!-- 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>

我有一个简单的方法来解决这个问题

使用
模式
而不是
ng模式

如果你有源代码,你会发现
pattern
ng pattern
是同一个指令

模式
ng模式
之间有两种不同:
1. angular将观察模式变化。(这就是我们需要的!)
2.angular将在模式前面加上“$”和“$”

$scope.regex = '\\d\\d'; //angular will convert this to ^\d\d$
$scope.UPPERCASE = '\\D\\D';
HTML:



这会破坏其他验证吗?像required和ng max length?我只能通过将第一个watch函数返回到
new RegExp
中的
eval
来实现这一点。
$scope.updatePattern = function() {
    var postalCode = $scope.genericAddressEntry.postalCode;
    postalCode.$setViewValue(postalCode.$viewValue);
};
$scope.regex = '\\d\\d'; //angular will convert this to ^\d\d$
$scope.UPPERCASE = '\\D\\D';
<input name="test" pattern="regex">
<!-- I can use filter to change my wrong UPPERCASE regex to correct.-->
<input name="test2" pattern="UPPERCASE | lowercase">