Reputation: 191
I want to check the changing of a value in a custom directive.
To do this, I use $parsers unshift-function to add my own function
But, my own function is not called!
This is my view:
<div ng-controller="MyCtrl">
<form novalidate name="myForm">
Number: <even-number name="awesomeField" ng-model="val"></even-number>
</form>
</div>
This is my javasript code:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.val = "42";
$scope.$watch('val', function() {
console.log("Controller: "+$scope.val);
});
}
myApp.directive('evenNumber', function(){
var tmplt = ''+
'<div class="input-group">'+
'<input class="form-control" name="inputDate" type="text" data-ng-model="ngModel"/>'+
'<span class="input-group-btn">'+
'<button class="btn btn-default">Default</button>'+
'</span>'+
'</div>';
return {
restrict: 'E',
require:'ngModel',
replace: true,
template: tmplt,
scope: {
ngModel: "="
},
link: function(scope, elem, attrs, ctrl){
ctrl.$parsers.unshift(checkValue);
function checkValue(viewValue){
console.log("halllllo");
return viewValue;
}
} // end link
}; // end return
});
What's the problem here?
Here it is as a jsFiddle
Upvotes: 3
Views: 279
Reputation: 4839
Write your directive as an attribute directive to be used on the <input />
element what ngModel knows how to handle already. Wrapping the input like that will not work with ngModel. You will need two directives to achieve what you need. One that bundles the input and the button (event-number) and a second one that attaches to the input itself to perform any conversions using $parsers model --> view
& $formatters view --> model
.
Update Here is a working example:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.val = "42";
$scope.$watch('val', function() {
console.log("Controller: "+$scope.val);
});
}
myApp
.directive('evenNumberConverter', function(){
return {
restrict: 'A',
require:'ngModel',
link: function(scope, elem, attrs, ctrl){
ctrl.$parsers.unshift(checkValue);
function checkValue(viewValue){
console.log("halllllo");
return viewValue;
}
} // end link
}; // end return
})
.directive('evenNumber', function(){
var tmplt = ''+
'<div class="input-group">'+
'<input class="form-control" name="inputDate" type="text" even-number-converter data-ng-model="value"/>'+
'<span class="input-group-btn">'+
'<button class="btn btn-default" data-ng-click="setDefault()">Default</button>'+
'</span>'+
'</div>';
return {
restrict: 'E',
replace: true,
template: tmplt,
scope: {
value: "="
},
link: function(scope, elem, attrs, ctrl){
scope.setDefault = function() {
scope.value = 0;
};
} // end link
}; // end return
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form novalidate name="myForm">
Number ({{val}}): <even-number name="awesomeField" value="val"></even-number>
</form>
</div>
Notes:
the thing is that your directive does not use any of the ngModelController
methods for sending the value to the view compontent and reading it back to the model. Its a simple "wrapper" directive and as such the ngModel on the scope could as well be named any other way.
This is because the ngModel directive does not know anything about your "even-number" element. In order to do so you would have to override and use the $render()
method to present the value and when reading from UI a new value use the $setViewValue()
. Only then the $parsers and $formatters are triggered, otherwise an ngModel scope variable behaves as any other.
Upvotes: 1