我想在angular中创建指令,如果输入的值不是有效格式,则会显示错误消息。 我最终带来的是:
http://plnkr.co/edit/l2CWu8u6sMtSj3l0kdvd?p=preview
app.directive('kbDecimalValidation', function ($parse, $rootScope, $compile) {
return {
restrict: 'E',
scope: {
inputFieldRef: '=?',
kbModel: '=ngModel',
kbRequired: '@required',
inputName: '@'
},
template: '<span ng-form="kbDecimalValidationForm">' +
'<input ng-model="kbModel" ng-required="kbRequired" ' +
'size="6"' +
'ng-pattern="/^[0-9]+(\\.[0-9][0-9]?)?$/" ' +
'/>' +
'<div ng-show="!kbDecimalValidationForm[inputName].$valid && kbDecimalValidationForm[inputName].$error.required"' +
'style="color: red; font-weight: bold">Field is required</div>' +
'<div ng-show="!kbDecimalValidationForm[inputName].$valid && kbDecimalValidationForm[inputName].$error.pattern"' +
'style="color: red; font-weight: bold">Bad format format,<br />allowed: "0.00"' +
'</div>' +
'</span>',
replace: true,
priority: 50,
controller: function($scope){
$scope.$watch(
'kbDecimalValidationForm[inputName]',
function (value) {
$scope.inputFieldRef = value;
});
},
compile: function (tElement, tAttrs, transclude) {
if($.tempKbDecimalValidationGUID == undefined){
$.tempKbDecimalValidationGUID = 0;
}
var guidInputName = 'XXX' + ++$.tempKbDecimalValidationGUID + 'XXX';
$(tElement).find('input').attr('name', guidInputName); //it is here to force angular to assign value to: $scope.kbDecimalValidationForm[guidInputName]
//there is no expression in name, so angular won't add it to $$watchers
return {
pre: function preLink($scope, iElement, iAttrs, controller) {
//$(iElement).find('input').attr('name', iAttrs.inputName); //it doesn't work if there is expression in inputName,
// expression will be evaluated later (after linkFunction)
// and the name assigned here will be updated (re-parsed by angular watch)
},
post: function postLink($scope, iElement, iAttrs, controller) {
$scope.kbDecimalValidationForm[iAttrs.inputName] = $scope.kbDecimalValidationForm[guidInputName]; //rewrite value to make it available by parsed name
$(iElement).find('input').attr('name', iAttrs.inputName); //assign parsed name - GUID didn't contain expression, so it is not in $$watchers,
// so it won't be replaced by angular
}
}
}
};
});
但我确信不是这样做的方式。我用它来解决很多问题。有人能告诉我实现它的方法是什么?
PS:我现在遇到的上述指令的问题是:当我在ng-repeat中使用它时,并重新排序重复的源指令不能正常工作。我怀疑问题出在我的“黑客编码”(tempKbDecimalValidationGUID和$ scope.kbDecimalValidationForm变量)
答案 0 :(得分:0)
对于Angular 1.2.x,您必须使用ngModel.$parsers
和$formatters
管道进行验证。 Angular 1.3具有专用的$validators
甚至$asyncValidators
管道。因此, 1.2.x 的验证解决方案的大纲将是:
.directive("kbDecimalValidation", function() {
function parseDecimal(value) {
// implement the conversion from a string to number, e.g. (simpistic):
var val = parseFloat(value);
// return a number (for success), null (for empty input), or a string (describing the error on error)
}
function formatDecimal(value) {
// format a number to a string that will be displayed; the inverse of parseDecimal()
// throw error if something goes wrong
}
return {
restrict: "A",
require: "ngModel",
link: function(scope, elem, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
var val = parseDecimal(value);
if( typeof val === "string" ) {
// an error occured
ngModel.$setValidity("kbDecimal", false);
// return undefined!
}
else {
ngModel.$setValidity("kbDecimal", true);
return val;
}
});
ngModel.$formaters.push(function(value) {
if( value == null || typeof value === "number" ) {
ngModel.$setValidity("kbDecimal", true);
try {
return formatDecimal(value);
}
catch(e) {
ngModel.$setValidity("kbDecimal", false);
return "";
}
}
else {
ngModel.$setValidity("kbDecimal", false);
return "";
}
});
}
};
})
许多细节都需要工作,但希望你能得到这个想法。 parseDecimal()
/ formatDecimal()
函数甚至可以转到专用的Angular服务,如果它们变得过于复杂,或者需要可重用。
快速而肮脏的方法是通过elem
的{{1}}参数使用DOM操作。 E.g:
link()
另一种方法,不那么快,但组件化程度更高的是另外两个指令。一个将放在link: function(scope, elem, attrs, ngModel) {
...
scope.$watch(
function() { return ngModel.$error.kbDecimal; },
function(newval) {
var container = elem.parent();
// append or remove the message as necessary
...
}
);
}
元素(容器)上,另一个将显示消息。 HTML就像:
<span ng-form>
<span ng-form="..." validation-container>
<input ... kb-decimal-validation />
<validation-messages></validation-messages>
</span>
和kbDecimalValidation
都需要validationMessages
; validationContainer
的控制器将有一个方法,由validationContainer
调用,以获得有关kbDecimalValidation
对象的通知。它还将公开$error
对象的副本。 $error
将validationMessages
对象并显示或隐藏相应的消息。