Reputation: 1208
Say I have the following directive:
myApp.directive('myDirective', function() {
return {
restrict: 'A',
require: 'ngModel',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs, ngModelCtrl) {
scope.$watch('ngModel', function() {
ngModelCtrl.$modelValue = 'foo';
});
}
}
});
And the following html:
<input ng-model="name" my-directive></input>
Basically, whenever the user changes the input, my-directive
would ideally change the internal model value to "foo" while leaving the view value untouched.
But when I print out $scope.name
in the corresponding controller, it doesn't log "foo", it logs whatever the user entered in.
It would seem that ngModelCtrl.$modelValue
is not what the controller is accessing -- am I approaching this problem incorrectly?
(Also watching the ngModel
in the scope feels really wrong, but I'm not sure of any other way. Any suggestions would be much appreciated!)
Upvotes: 10
Views: 12920
Reputation: 123739
If you are looking for view change, you should never register a watch. ngModelController's $viewChangeListeners
are specifically designed for this purpose and to avoid creating any additional watch on the ngModel. You can also remove 2 way binding set up on the ngModel.
I can think of this way.
.directive('myDirective', function($parse) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attrs, ngModelCtrl) {
/*Register a viewchange listener*/
ngModelCtrl.$viewChangeListeners.push(function(){
/*Set model value differently based on the viewvalue entered*/
$parse(attrs.ngModel).assign(scope, ngModelCtrl.$viewValue.split(','));
});
}
}
});
While thinking about it the other way around (Credits @Cody) it becomes more concise and appropriate while using a $parser
.
ngModelCtrl.$parsers.push(function(val) { return val.split(',') });
Upvotes: 11