Reputation: 2330
Hi I am writing a directive that does some custom input element validation based on a json object that is passed via an attribute directive. I am adding an ng-blur and ng-focus in the compile phase binding to two functions in my directive controller. however. when I run my code initially the input field does not contain a value altough when I click in it and the blur is triggered I can see in debug that ngModel does contain the value. I am thinking that the view is not updated the first time but I don't understand what is causing it. Here is my code.
'use strict';
angular.module('zendantennesApp')
.directive('validation', function ($compile, $parse) {
return {
scope: {
validation: '@'
},
require: "?ngModel",
restrict: 'A',
compile: function(el, attrs) {
el.removeAttr('validation');
el.attr('ng-blur', 'evaluateExpression()');
el.attr('ng-focus', 'assignOriginalValue()');
var fn = $compile(el);
return function(scope, element, attrs, ngModel){
ngModel.$render = function(){
$(element).val(ngModel.$viewValue);
};
fn(scope);
}
},
controller: function($scope){
$scope.originalValue = $scope.ngModel;
$scope.validationObject = JSON.parse($scope.validation.replace(/'/g, '"'));
$scope.evaluateExpression = function(){
console.log(validationObject);
};
$scope.assignOriginalValue = function(){
$scope.originalValue = $scope.ngModel;
}
}
}
});
my html:
<input validation="{'min':0, 'max':5}" tabindex="45" type='text' class='form-control' ng-model="aanpassing.nieuweAntenne.elektrischeTilt"/>
I added a plunkr to illustrate the problem:
https://plnkr.co/edit/1qYxCiSZWHgVeN9CEpxw?p=info
if anyone could help that would be greatly appreciated
Upvotes: 1
Views: 753
Reputation: 3586
The plunkr I provided in the comment seems to work, so I'll put it as a answer.
Instead of using compile on the directive it is possible to use the linking function directly:
app.directive('validation', function ($compile, $parse) {
return {
scope: {
validation: '@'
},
require: "ngModel",
restrict: 'A',
link: function(scope, element, attrs, ngModel){
scope.validation = scope.validation.replace(/'/g, '"');
var validation = JSON.parse(scope.validation);
for(prop in validation){
if(validation.hasOwnProperty(prop)){
setUpValidators(prop);
}
}
function setUpValidators(val){
switch(val){
case 'min':
ngModel.$validators.min = function(modelValue, viewValue){
var value = modelValue || viewValue;
return value.length >= validation.min;
};
break;
case 'max':{
ngModel.$validators.min = function(modelValue, viewValue){
var value = modelValue || viewValue;
return value.length <= validation.max;
};
break;
}
}
}
ngModel.$render = function(){
element.val(ngModel.$viewValue);
};
}
};
});
This will set up validator on the ngModel based on the provided object to the validate
-directive.
If you want to wait with validating until after the input is blurred you could use ngModelOptions
like this: ng-model-options="{updateOn: 'blur'}"
on the input element.
When doing like this you don't need to add any ng-blur or ng-focus on the element in the compile step.
Upvotes: 1