从内部指令
我已经创造了一些指令,它们帮我检查输入的有效性,看起来或多或少像这样的形式检索输入验证错误:从内部指令
app.directive("initialDate", function(){
return{
require: '?ngModel',
restrict:"A",
link:function(scope, element, attrs, ngModel){
scope.$watch(attrs.ngModel, function() {
validate();
});
attrs.$observe('initialDate', function() {
validate();
});
var validate = function() {
var date = Date.parse(ngModel.$viewValue);
var initialDate = Date.parse(attrs.initialDate);
ngModel.$setValidity('initial-date', date >= initialDate);
}
}
}
});
现在,我想自定义消息添加到输入,选择等等,这些都没有通过验证,但我不想一个接一个地用ng-if添加一个span或somethinng(这是我想避免的很多工作)。
我第一次尝试是创建这样的指令:所以现在
app.directive("ngInvalid", function(){
restrict:"C",
...
});
但是didn't工作我正尝试这一
app.directive("input", function(){
return {
require:"?ngModel",
link:function(scope, element, attrs, ctrl){
scope.$watch(function() {
return element.attr('class');
}, function(newVal, oldVal){
if (newVal == oldVal) return;
if (element.hasClass("ng-invalid")){
element.parent().append("<span class = 'error' style='color:red'>There was an error</span>");
}else{
element.parent().find(".error").remove();
}
});
}
}
});
所以,这一个工程(更或更少,它需要更多的工作,嘿嘿),但我将不得不创建一个选择,textareas等,并对每种类型的错误进行一些检查,如果我想显示自定义消息。
此外,它真的看起来很脏。我真的觉得一定有什么事情,我可以说看起来更像这个指令内做到:
...
link:function(scope, element, attrs, ctrl){ /***element is the input or select or textarea... ***/
if (!element.$isValid){
switch (element.$validationErrors[0]){
case "emailValidation": element.parent().append("<span class = 'error' style='color:red'>Email format not correct</span>"); break;
case "initialDate": element.parent().append("<span class = 'error' style='color:red'>Date cannot be previous to {{initialDate}}</span>"); break;
case "pattern": element.parent().append("<span class = 'error' style='color:red'>Format incorrect</span>"); break;
}
}
}
...
我一直在寻找在文档和浏览的一些问题,但主要是我发现需要使用的解决方案表单控制器,我想避免这种情况。
是否有一些方法可以让我从输入中检索错误?
编辑
要清楚,let's说,输入没有包装形式的标签里面,但股利,或别的东西。我如何访问输入指令中的每个错误?
简答
不,it's无法访问有效性检查,而不表单控件。
解决方法
我使用的输入指令来实现我想要的东西,但它doesn't似乎太高雅了,我(我倒是很喜欢使用文本域影响而不必选择指令我-定制指令添加到每个领域我想验证)
(function(){
var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2);
const E_UNKNOWN = 0,
E_REQUIRED = 1,
E_NAN = 2,
E_MIN = 3,
E_MAX = 4,
E_EMAIL = 5,
E_MINLEN = 6,
E_MAXLEN = 7,
E_PATTERN = 8,
E_BLACKLIST = 9,
E_EQUAL = 10;
E_INITIALDATE = 11;
const ERR_MESSAGES = [
{'es':'Error desconocido', 'en':'Unknown Error'},
{'es':'Este campo es obligatorio', 'en':'This field is mandatory'},
{'es':'Este campo debe ser numérico', 'en':'This field should be numeric'},
{'es':'El valor es inferior al mínimo', 'en':'Value is lower than the minimum'},
{'es':'El valor es superior al máximo', 'en':'Value is higher than the maximum'},
{'es':'El formato de email no es válido', 'en':'Email format incorrect'},
{'es':'No cumple longitud mínima', 'en':'Minimum length not matched'},
{'es':'No cumple longitud máxima', 'en':'Maximum length not matched'},
{'es':'El formato no es válido', 'en':'Format incorrect'},
{'es':'Este valor no está permitido', 'en':'This value is not allowed'},
{'es':'Los campos no coinciden', 'en':'Fields doesn´t match'},
{'es':'La fecha es anterior a la fecha inicial', 'en':'This date is previous to the initial date'},
];
var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2);
app.directive("input", function(){
return {
scope:{},
link:function(scope, element, attrs, ctrl, ngModel){
scope.blurred = false;
element[0].addEventListener("blur", function(){
scope.blurred = true;
element.parent().find(".error").remove();
checkValidity();
});
var checkValidity = function(){
var classList = element.attr('class');
if (!classList) return;
var matches = classList.match(/ng-invalid-(.*?)(\s|$)/);
if (matches == null) return;
if (!(1 in matches)) return;
var $err = matches[1];
var $errMessage = "";
switch($err){
case "required": $errMessage = ERR_MESSAGES[E_REQUIRED][lang]; break;
case "number": $errMessage = ERR_MESSAGES[E_NAN][lang]; break;
case "min": $errMessage = ERR_MESSAGES[E_MIN][lang]; break;
case "max": $errMessage = ERR_MESSAGES[E_MAX][lang]; break;
case "email": $errMessage = ERR_MESSAGES[E_EMAIL][lang]; break;
case "minlength": $errMessage = ERR_MESSAGES[E_MINLEN][lang]; break;
case "maxlength": $errMessage = ERR_MESSAGES[E_MAXLEN][lang]; break;
case "pattern": $errMessage = ERR_MESSAGES[E_PATTERN][lang]; break;
case "blacklist": $errMessage = ERR_MESSAGES[E_BLACKLIST][lang]; break;
case "equals": $errMessage = ERR_MESSAGES[E_EQUAL][lang]; break;
case "initial-date": $errMessage = ERR_MESSAGES[E_INITIALDATE][lang]; break;
default: $errMessage = ERR_MESSAGES[E_UNKNOWN][lang]; break;
}
if (element.hasClass("ng-invalid")){
element.parent().append("<span class = 'error'>"+$errMessage+"</span>");
}
}
}
}
});
})();
这里是一个链接到一个工作codepen:http://codepen.io/sergio0983/pen/AXxNpN?editors=1111
出于某种原因,在codepen中,如果我不在角元素上使用$选择器,错误不会被删除()
我发布的上一个方法有一些问题。对班级的监视并不像预期的那样工作,当班级实际发生变化时并没有被解雇,而是当下一个输入字符被输入时。例如,所需的错误是在空白后在输入中引入了一个新的字符,并且控制台中的日志和检查器中的类是不同的(可能是有角度的错误)。
反正,我已经找到我认为是更好的解决方案:哦,it's实际上可以访问有效性检查时的控制是不是一个形式的标签
That's里面包裹代码(我didn't添加一个模糊账了,但应该很容易)
var errMsgDirective = function(){
return{
restrict:"E",
require:"?ngModel",
link:function(scope, element, attrs, ctrl, ngModel){
if (!attrs.ngModel) return;
var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2);
const E_UNKNOWN = 0, E_REQUIRED = 1, E_NAN = 2, E_MIN = 3, E_MAX = 4, E_EMAIL = 5, E_MINLEN = 6, E_MAXLEN = 7, E_PATTERN = 8, E_BLACKLIST = 9, E_EQUAL = 10; E_INITIALDATE = 11;
const ERR_MESSAGES = [
{'es':'Error desconocido', 'en':'Unknown Error'},
{'es':'Este campo es obligatorio', 'en':'This field is mandatory'},
{'es':'Este campo debe ser numérico', 'en':'This field should be numeric'},
{'es':'El valor es inferior al mínimo', 'en':'Value is lower than the minimum'},
{'es':'El valor es superior al máximo', 'en':'Value is higher than the maximum'},
{'es':'El formato de email no es válido', 'en':'Email format incorrect'},
{'es':'No cumple longitud mínima', 'en':'Minimum length not matched'},
{'es':'No cumple longitud máxima', 'en':'Maximum length not matched'},
{'es':'El formato no es válido', 'en':'Format incorrect'},
{'es':'Este valor no está permitido', 'en':'This value is not allowed'},
{'es':'Los campos no coinciden', 'en':'Fields doesn´t match'},
{'es':'La fecha es anterior a la fecha inicial', 'en':'This date is previous to the initial date'},
];
var checkValidity = function(){
if (!ctrl.$touched) return;
var errors = [];
for (var i in ctrl.$error){
if (ctrl.$error[i] == false) continue;
switch (i){
case "required": errors.push(ERR_MESSAGES[E_REQUIRED][lang]); break;
case "number": errors.push(ERR_MESSAGES[E_NAN][lang]); break;
case "min": errors.push(ERR_MESSAGES[E_MIN][lang]); break;
case "max": errors.push(ERR_MESSAGES[E_MAX][lang]); break;
case "email": errors.push(ERR_MESSAGES[E_EMAIL][lang]); break;
case "minlength": errors.push(ERR_MESSAGES[E_MINLEN][lang]); break;
case "maxlength": errors.push(ERR_MESSAGES[E_MAXLEN][lang]); break;
case "pattern": errors.push(ERR_MESSAGES[E_PATTERN][lang]); break;
case "blacklist": errors.push(ERR_MESSAGES[E_BLACKLIST][lang]); break;
case "equals": errors.push(ERR_MESSAGES[E_EQUAL][lang]); break;
case "initial-date": errors.push(ERR_MESSAGES[E_INITIALDATE][lang]); break;
default: errors.push(ERR_MESSAGES[E_UNKNOWN][lang]); break;
}
}
element.parent().find(".error").remove();
if (errors.length == 0){
}else{
$errMessage = errors.join("; ");
element.parent().append("<span class = 'error'>"+$errMessage+"</span>");
}
}
scope.$watch(function(){
return JSON.stringify(ctrl.$error);
}, function(){
checkValidity();
});
scope.$watch(function(){
return ctrl.$touched;
}, function(){
checkValidity();
})
}
}
}
app.directive("input", errMsgDirective);
app.directive("textarea", errMsgDirective);
app.directive("select", errMsgDirective);
有一些事情我想指出:
1:我可以访问相对于里面的每个控制所有错误指令与ctr l。$错误(为了上帝的缘故,为什么在所有堆栈溢出中没有一个单一的答案,说你可以用。$ error?来访问控制错误。 ¬¬)
第二:我有一个真正的困难时期将是工作的手表:我尝试了所有的以下内容:
scope.$watch(attrs.ngModel, function(){...}) //This one did not work because the model doesn´t change when the validity checks are not met
scope.$watch(ctrl.$valid, function(){...}) //Never fired
scope.$watch(ctrl.$invalid, function(){...}) //Never fired
scope.$watch(ctrl.$error, function(){...}) //Never fired
scope.$watch(function(){ return ctrl.$error }, function(){...}) //Never fired
scope.$watch(function(){ return JSON.stringify(ctrl.$error) }, function(){...}) //BINGO!!!
在这里你可以看到它的工作:
看一下ng-messages – dewd
看起来不错,但并不能解决我想要实现的两件事:如果我想在每个字段上显示一个显示错误,则不依赖于使用表单并必须为每个输入创建一个组件。 – sergio0983