Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scope.$watch in directive link function not getting called

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?

like image 626
Johan Alkstål Avatar asked Oct 09 '13 19:10

Johan Alkstål


2 Answers

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;
    });
  }
like image 59
jusio Avatar answered Dec 07 '22 02:12

jusio


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.

like image 29
Michael Benford Avatar answered Dec 07 '22 02:12

Michael Benford