我有一个包含常规文本输入的简单html表单。输入上设置了ng-minlength
,ng-maxlength
和ng-pattern
角度built-in form input directives。
问题:ng-pattern
检查是在ng-minlength
和ng-maxlength
进行长度检查之前应用的。{/ p>
问题:如何更改默认检查顺序:即首先检查长度,然后应用模式检查?
示例:
<body ng-app>
<div>
<form name="myForm">
Name: <input name="name" type="text" ng-model="name" ng-minlength="3" ng-maxlength="16" ng-pattern="/^\w+$/"/>
<div ng-show="myForm.name.$dirty && myForm.name.$invalid">
<span ng-show="myForm.name.$error.pattern">Pattern error</span>
<span ng-show="myForm.name.$error.minlength || myForm.name.$error.maxlength">Length error</span>
</div>
<br/>
<input type="submit" value="Submit">
</form>
</div>
</body>
当前行为:
期望的行为:
仅供参考,相关jsfiddle。
提前致谢。
答案 0 :(得分:5)
编写自己的指令:
var mod = angular.module("myApp", []);
mod.directive("nameValidation", function () {
return {
restrict: "A",
require: "ngModel",
link: function (scope, element, attrs, ngModelCtrl) {
var validate = function (value) {
var minLen = parseInt(attrs.myMinlength, 10),
maxLen = parseInt(attrs.myMaxlength, 10),
pattern = attrs.myPattern,
match = pattern.match(/^\/(.*)\/([gim]*)$/),
lenErr = false;
if (match) {
pattern = new RegExp(match[1], match[2]);
}
if (!ngModelCtrl.$isEmpty(value)) {
ngModelCtrl.$setValidity("pattern", true);
if ((minLen && value.length < minLen) || (maxLen && value.length > maxLen)) {
ngModelCtrl.$setValidity("length", false);
lenErr = true;
}
else {
ngModelCtrl.$setValidity("length", true);
lenErr = false;
}
if (!lenErr) {
if (match && !pattern.test(value)) {
ngModelCtrl.$setValidity("pattern", false);
}
else {
ngModelCtrl.$setValidity("pattern", true);
}
}
}
else {
ngModelCtrl.$setValidity("length", true);
ngModelCtrl.$setValidity("pattern", true);
}
}
ngModelCtrl.$parsers.push(validate);
ngModelCtrl.$formatters.push(validate);
}
}
});
然后在HTML中,包含应用程序并使用指令:
<body ng-app="myApp">
<div>
<form name="myForm">
Name: <input name="name" type="text" ng-model="name" name-validation="" my-minlength="3" my-maxlength="16" my-pattern="/^\w+$/"/>
<div ng-show="myForm.name.$dirty && myForm.name.$invalid">
<span ng-show="myForm.name.$error.pattern">Pattern error</span>
<span ng-show="myForm.name.$error.length">Length error</span>
</div>
<br/>
<input type="submit" value="Submit">
</form>
</div>
</body>
该指令使用my-minlength,my-maxlength和my-pattern作为三个值。如果长度失败,那将首先跳闸。如果没有,那么如果模式不匹配,则模式将显示为错误。如果你想在名称以外的地方使用它,可以考虑重命名这个指令,因为minlength,maxlength和pattern可以通过属性传递给它。如果它们被取消,它们将被忽略。
参见jsfiddle:http://jsfiddle.net/4zpxk/6/
答案 1 :(得分:2)
我在角度代码中搜索了这个行为的原因。然后在函数'textInputType'中,它是处理角度'input'指令的文本输入的特定函数,我在这个函数的末尾找到了它,在那里我们可以看到三个代码块。
// pattern validator
if (pattern){
//validator logic
}
// min length validator
if (attr.ngMinlength) {
//validator logic
}
// max length validator
if (attr.ngMaxlength) {
//validator logic
}
因此,无论你是否更改了html输入元素中ng- *属性的声明顺序,你总会得到相同的结果,但是如果你改变了块的顺序,我的意思是,先放入min length validator block模式验证器块你将得到你期望的结果。
这是一个解决你的问题的方法,但你必须对角度代码做一个小小的改变,我不知道你是否真的喜欢这个。但是你有一个非常普遍的情况,即验证概念的声明顺序很重要,因此,必须采取更多措施来处理这个问题。感谢
答案 2 :(得分:1)
不幸的是,您无法更改默认检查顺序。
一种解决方案是编写自定义验证器,而不是那么困难。根据{{3}},我想出了这段代码(this answer)
用法:范围内有一系列验证函数,它们将传递给我们的自定义指令"validators"
:
<input name="name" type="text" ng-model="name" validators="nameValidators"/>
验证器函数看起来像(例如minlength
约束):
function minlength(value, ngModel) {
if( value == null || value == "" || value.length >= 3 ) {
ngModel.$setValidity('minlength', true);
return value;
}
else {
ngModel.$setValidity('minlength', false);
return;
}
}
重点是:它取值和ngModel
作为参数,执行测试(此处value.length >= 3
)并根据需要调用ngModel.$setValidity()
。
该指令使用ngModel.$parsers
注册给定的函数:
app.directive("validators", function($parse) {
return {
restrict: "A",
require: "ngModel",
link: function(scope, el, attrs, ngModel) {
var getter = $parse(attrs.validators),
validators = getter(scope),
i;
for( i=0; i < validators.length; i++ ) {
ngModel.$parsers.push((function(index) {
return function(value) {
return validators[index](value, ngModel);
};
})(i));
}
}
};
});
可以调整和改进许多细节,但大纲有效(再次链接到fiddle)。现在,验证顺序由nameValidators
数组中的验证器函数的顺序显式设置。
答案 3 :(得分:1)
如果您使用ng-messages,您应该能够通过ng-message元素的顺序设置顺序,例如:
<div ng-messages="field.$error">
<ul class="validation-errors">
<li ng-message="required">This has the highest prio</li>
<li ng-message="min">Second in command</li>
<li ng-message="max">I'm last</li>
</ul>
</div>
此外的文档:https://docs.angularjs.org/api/ngMessages/directive/ngMessages
答案 4 :(得分:0)
我刚刚更改了指令的顺序,首先是模式
<input name="name" type="text" ng-model="name" ng-pattern="/^\w+$/" ng-minlength="3" ng-maxlength="16"/>
编辑:uuum,测试你的fiddel没有变化,它显示了你想要的行为...... 指令是按优先级编制的,但我不知道如何设置angulars指令优先级...对不起,应该先测试一下