[英]decimal validation directive in angularjs
I wanted to create directive in angular that would display error message if entered value is not in valid format. 我想创建角度指令,如果输入的值格式无效,该指令将显示错误消息。 What I finally came with is: 我最终想到的是:
http://plnkr.co/edit/l2CWu8u6sMtSj3l0kdvd?p=preview http://plnkr.co/edit/l2CWu8u6sMtSj3l0kdvd?p=预览
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
}
}
}
};
});
but I'm sure it is not propper way to do it. 但我敢肯定这不是正确的方法。 I expirience a lot of problems with it. 我觉得有很多问题。 Can somebody tell me what is the propper way to achieve it? 有人可以告诉我实现该目标的正确方法是什么?
PS: The problem I'm facing right now with the above directive is: when I use it in ng-repeat, and reorder repeated source the directive does not work correctly. PS:我现在使用上述指令遇到的问题是:当我在ng-repeat中使用它时,并对重复的源进行重新排序时,该指令无法正常工作。 I suspect the problem is with my "hacking coding" (the tempKbDecimalValidationGUID, and $scope.kbDecimalValidationForm variables) 我怀疑问题出在我的“黑客编码”上(tempKbDecimalValidationGUID和$ scope.kbDecimalValidationForm变量)
For Angular 1.2.x, you will have to use the ngModel.$parsers
and $formatters
pipelines for validation. 对于Angular 1.2.x,您将必须使用ngModel.$parsers
和$formatters
管道进行验证。 Angular 1.3 has the dedicated $validators
and even $asyncValidators
pipelines. Angular 1.3具有专用的$validators
甚至$asyncValidators
管道。 So the outline of a validation solution for 1.2.x would be: 因此,针对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 "";
}
});
}
};
})
Many details will need work, but hopefully you get the idea. 许多细节都需要工作,但希望您能理解。 The parseDecimal()
/ formatDecimal()
functions could even go to a dedicated Angular service, if they become too complex, or need to be reusable. 如果parseDecimal()
/ formatDecimal()
函数变得过于复杂或需要可重用,它们甚至可以使用专用的Angular服务。
A quick and dirty way is to use DOM manipulation through the elem
argument of link()
. 一种快速而肮脏的方法是通过link()
的elem
参数使用DOM操作。 Eg: 例如:
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
...
}
);
}
Another way, less quick but more componentized is to make 2 more directives. 另一种方式,较慢但更组件化的是再增加2条指令。 One will be placed on the <span ng-form>
element (the container), another will display the messages. 一个将放置在<span ng-form>
元素(容器)上,另一个将显示消息。 The HTML would be like: HTML将像:
<span ng-form="..." validation-container>
<input ... kb-decimal-validation />
<validation-messages></validation-messages>
</span>
Both kbDecimalValidation
and validationMessages
will require the validationContainer
; 无论kbDecimalValidation
和validationMessages
将需要validationContainer
; the controller of the validationContainer
will have a method, called by the kbDecimalValidation
, to get notified about the $error
object. 该的控制器validationContainer
将有一个方法,由被叫kbDecimalValidation
,以收到通知的$error
对象。 It will also expose a copy of the $error
object. 它还将公开$error
对象的副本。 The validationMessages
will $watch
that object and display or hide the appropriate messages. validationMessages
将$watch
对象,并显示或隐藏适当的消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.