I have a validation directive called valid-number
that is used to set the validity of a form using $setValidity - this works fine for any text values that I type into the input box that have the directive applied to as an attribute.
The HTML is
<form name="numberForm">
<input name="amount" type="text" ng-model="amount" required valid-number /></form>
The directive is as follow
angular.module('test',[]).directive('validNumber',function(){
return{
require: "ngModel",
link: function(scope, elm, attrs, ctrl){
var regex=/\d/;
ctrl.$parsers.unshift(function(viewValue){
var floatValue = parseFloat(viewValue);
if(regex.test(viewValue)){
ctrl.$setValidity('validNumber',true);
}
else{
ctrl.$setValidity('validNumber',false);
}
return viewValue;
});
}
};
});
However, I would also like the validation to be triggered and set the css to an invalid clsss if the value the input box is initialised to when the page is first loaded is invalid, eg if I set $scope.amount = 'not a number'
I would expect the input box to have had the directive applied to it, but no joy. In order for not a number
to be highlighted as invalid I have to make a change to the contents of the input, which triggers the directive.
How can I ensure the directive applies to whatever the <input>
is initialised with?
A full code example is here;
/
I have a validation directive called valid-number
that is used to set the validity of a form using $setValidity - this works fine for any text values that I type into the input box that have the directive applied to as an attribute.
The HTML is
<form name="numberForm">
<input name="amount" type="text" ng-model="amount" required valid-number /></form>
The directive is as follow
angular.module('test',[]).directive('validNumber',function(){
return{
require: "ngModel",
link: function(scope, elm, attrs, ctrl){
var regex=/\d/;
ctrl.$parsers.unshift(function(viewValue){
var floatValue = parseFloat(viewValue);
if(regex.test(viewValue)){
ctrl.$setValidity('validNumber',true);
}
else{
ctrl.$setValidity('validNumber',false);
}
return viewValue;
});
}
};
});
However, I would also like the validation to be triggered and set the css to an invalid clsss if the value the input box is initialised to when the page is first loaded is invalid, eg if I set $scope.amount = 'not a number'
I would expect the input box to have had the directive applied to it, but no joy. In order for not a number
to be highlighted as invalid I have to make a change to the contents of the input, which triggers the directive.
How can I ensure the directive applies to whatever the <input>
is initialised with?
A full code example is here;
http://jsfiddle.net/JW43C/5/
Share Improve this question asked Jun 9, 2013 at 15:41 GrahamBGrahamB 5691 gold badge6 silver badges19 bronze badges3 Answers
Reset to default 16$parsers
array contains a list of functions that will be applied to the value that model receives from the view (what user types in), and $formatters
array contains the list of functions that are being applied to the model value before it's displayed in the view.
In your directive you correctly used the $parsers
array, but you also need to add the $formatters
array if you want the initial value to be validated:
angular.module('test',[]).directive('validNumber',function(){
return{
require: "ngModel",
link: function(scope, elm, attrs, ctrl){
var regex = /^\d$/;
var validator = function(value){
ctrl.$setValidity('validNumber', regex.test(value));
return value;
};
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
}
};
});
Demo plunker
You can simply call your verification function during the linking phase, like in this fiddle :
link: function(scope, elm, attrs, ctrl) {
var regex=/\d/;
var verificationFunction = function(viewValue) {
var floatValue = parseFloat(viewValue);
if(regex.test(viewValue)) {
ctrl.$setValidity('validNumber',true);
return viewValue;
}
else {
ctrl.$setValidity('validNumber',false);
return undefined;
}
};
ctrl.$parsers.unshift(verificationFunction);
verificationFunction();
}
After (>=) angular 1.3.1 version was released you could implement that behaviour with a little bit correct way, following angular validation directives style (e.g. required, maxlength).
In that case you have to append your validator as property of $validators
array and there are no need in $parsers
or $formatters
anymore:
var app = angular.module('test', []);
app
.directive('validNumber', function() {
return {
require: "ngModel",
link: function(scope, elm, attrs, ctrl) {
var regex = /^\d+$/;
ctrl.$validators['validNumber'] = function(modelValue, viewValue) {
return regex.test(viewValue);
};
}
};
});
app.controller('NumberCtrl', NumberCtrl);
function NumberCtrl($scope) {
$scope.amount = '5z';
};
input.ng-invalid {
background-color: #FA787E;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="NumberCtrl">
<div ng-form name="numberForm">
<input name="amount"
type="text"
ng-model="amount"
required
valid-number />
<span ng-show="numberForm.amount.$error.validNumber">
Doesn't look like an integer
</span>
</div>
</div>
</div>