$watch ngModel from inside directive using isolate scope

JavascriptAngularjsAngularjs Directive

Javascript Problem Overview


I am trying to watch my model value from inside my linking function.

scope.$watch(attrs.ngModel, function() {
       console.log("Changed"); 
    });

When I change the model value inside my controller, the $watch function is not triggered.

$scope.myModel = "ACT";

$timeout(function() {
   $scope.myModel = "TOTALS"; 
}, 2000);

Fiddle: http://jsfiddle.net/dkrotts/BtrZH/4/

What am I missing here?

Javascript Solutions


Solution 1 - Javascript

You'll need to watch a function that returns the $modelValue you're watching.

The following code shows a basic example:

app.directive('myDirective', function (){
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
           scope.$watch(function () {
              return ngModel.$modelValue;
           }, function(newValue) {
               console.log(newValue);
           });
        }
     };
});

Here's a plunker of the same idea in action.

Solution 2 - Javascript

The problem is that you $watching attrs.ngModel which is equal to "myModel". You do not have "myModel" bound in your scope. You want to $watch "model". That is what is bound in the scope of your directive. See http://jsfiddle.net/BtrZH/5/

Solution 3 - Javascript

The proper way to do this is:

app.directive('myDirective', function () {
  return {
	require: 'ngModel',
	link: function (scope, element, attrs, ngModel) {

		ngModel.$render = function () {
			var newValue = ngModel.$viewValue;
			console.log(newValue)
		};

	}
  };
});

Solution 4 - Javascript

Here is another way to do this:

app.directive('myDirective', function (){
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
           attrs.$observe('ngModel', function(value){ // Got ng-model bind path here
              scope.$watch(value,function(newValue){ // Watch given path for changes
                  console.log(newValue);  
              });
           });
        }
    };
});

Doing it that way you will be able to listen value changes with binds like that

Solution 5 - Javascript

This is an extension of @ Emmanuel's answer above to answer @Martin Velez, although I know it's pretty late! (Also I can't make comments yet, so if this isn't the right place for this, sorry!)

I'm not sure which version of Angular OP was using, but in Angular#1.2+ at least on the official docs https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$render, $render is listed like this:

> Called when the view needs to be updated. It is expected that the user > of the ng-model directive will implement this method. > > The $render() method is invoked in the following situations: > > $rollbackViewValue() is called. If we are rolling back the view value > to the last committed value then $render() is called to update the > input control. The value referenced by ng-model is changed > programmatically and both the $modelValue and the $viewValue are > different from last time. Since ng-model does not do a deep watch, > $render() is only invoked if the values of $modelValue and $viewValue > are actually different from their previous value.

I interpret this to mean that the correct way to $watch an ngModel from a directive is to require ngModel and implement a link function that injects ngModelController. Then use the ngModel API that's built in to $render-on-change ($watch), or whatever else.

Solution 6 - Javascript

There are 2 ways to do it.

  1. You can use $attrs.[any_attribute] and set on it any listener

  2. You can have isolated scope with 2 ways binding variable and set a listener on it.If you want more,here is a cool article

http://www.w3docs.com/snippets/angularjs/bind-variable-inside-angularjs-directive-isolated-scope.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDustinView Question on Stackoverflow
Solution 1 - JavascriptBen LeshView Answer on Stackoverflow
Solution 2 - Javascriptdnc253View Answer on Stackoverflow
Solution 3 - JavascriptEmmanuelView Answer on Stackoverflow
Solution 4 - Javascriptuser2978730View Answer on Stackoverflow
Solution 5 - JavascriptRoboBearView Answer on Stackoverflow
Solution 6 - JavascriptHazarapet TunanyanView Answer on Stackoverflow