$watch ngModel from inside directive using isolate scope

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?

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.

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/

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)
        };

    }
  };
});

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

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 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.

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