scope.$watch in directive link function not getting called

All we need is an easy explanation of the problem, so here it is.

I have this factory,

.factory('authentication', [function() {

    return {
      loginRequired: false
    };
  }]);

I have this controller,

.controller('TopNavCtrl', ['$scope', 'authentication', function($scope, authentication) {

  $scope.login = function() {
    authentication.loginRequired = true;
  };

}]);

and I have this link function in a directive,

link: function(scope, element, attrs) {

    scope.show = false;

    scope.$watch(authentication.loginRequired, function(value) {
      scope.show = value;
    });
  }

When authentication.loginRequired = true; is done in the controller, the scope.$watch in the directive isn’t called.

Any ideas why?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Scope.$watch accepts as first parameter expression or function. What you are passing as first parameter is a value stored in authetication.loginRequired.

Following will work (assuming you have correctly injected authetication factory):

link: function(scope, element, attrs) {

    scope.show = false;

    scope.$watch(function(){return authentication.loginRequired;}, function(value) {
      scope.show = value;
    });
  }

Method 2

Following up @jusio’s answer, it’s also possible to use a string expression as long as you make your factory part of the scope:

scope.authentication = authentication;
scope.$watch('authentication.loginRequired', function(value) {
...
});

That’s so because when a $watch is provided with a string expression, it evaluates that string against its scope.

You should decide whether it’s worth cluttering your directive’s scope so you can have an arguably more readable code. If you’re already doing it for another reason, then it’s no big deal.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply