在我的应用程序中,我有一个input
字段,如果用户输入特定字符串(基本上是与正则表达式匹配的字符串),则会显示div
。
(简化)HTML部分:
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
<input type="text" ng-model="searchText"/>
<div>Hello</div>
<div ng-show="isValid(searchText)">World !</div>
</div>
</div>
和我的控制员:
function TodoCtrl($scope) {
var reg = /20\d{2}/g;
$scope.isValid = function(str) {
console.log('Is valid?');
return reg.test(str);
}
}
当用户输入一年(由正则表达式验证)时,我收到以下错误:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["isValid(searchText); newVal: true; oldVal: false"],["isValid(searchText); newVal: false; oldVal: true"],["isValid(searchText); newVal: true; oldVal: false"],["isValid(searchText); newVal: false; oldVal: true"],["isValid(searchText); newVal: true; oldVal: false"]]
http://errors.angularjs.org/1.2.1/$rootScope/infdig?p0=10&p1=%5B%5B%22isVal…2isValid(searchText)%3B%20newVal%3A%20true%3B%20oldVal%3A%20false%22%5D%5D
at http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:78:12
at Scope.$digest (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:11472:19)
at Scope.$apply (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:11682:24)
at HTMLInputElement.listener (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:15653:13)
at http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:2562:10
at Array.forEach (native)
at forEach (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:300:11)
at HTMLInputElement.eventHandler (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js:2561:5)
以下是JsFiddle的链接:http://jsfiddle.net/U3pVM/6598/
我的代码有什么问题,以及如何增强它?
答案 0 :(得分:7)
它是g
末尾的reg
。当您在相同的字符串twise上测试相同的表达式时,第二次在第一次找到的内容之后进行搜索。因此,如果你从&#34; 2001。&#34;开始,该函数将返回true,然后再次调用,搜索剩余的&#34;。&#34;并返回false。
答案 1 :(得分:1)
您应该使用$watch
和范围变量,而不是使用函数的返回值来决定是否显示元素。
这一行是怎么回事:
reg.test(str)
对str
进行更改,这是对scope变量的引用,触发另一个摘要,导致无限循环。编辑:这是由于正则表达式具有全局标志,如另一个答案中所述。因此,结合角度消化循环的工作方式就可以了。
以下是使用$watch
的解决方案:
function TodoCtrl($scope) {
var reg = /20\d{2}/g;
var isValid = function(str) {
$scope.show = reg.test(str);
}
$scope.$watch('searchText',isValid);
}
答案 2 :(得分:0)
尝试在函数内移动reg变量。
function TodoCtrl($scope) {
$scope.isValid = function(str) {
var reg = /20\d{2}/g;
console.log('Is valid?');
return reg.test(str);
}
}
正如KarolisJuodelė所指出的那样,正则表达式存储了最后一个有效位置,而g符号导致第二个调用为假。通过在函数内局部移动变量,如果您仍想使用g符号,则reg变量是新的引用。
Angular评估函数两次以确保它不会改变,但实际上在第二次调用中,它返回false,然后是true,然后是false,等等。