scope.$watch in directive link function not getting called
Solution 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;
});
}
Solution 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.
![Johan Alkstål](https://i.stack.imgur.com/iSBhu.jpg?s=256&g=1)
Johan Alkstål
Updated on October 10, 2020Comments
-
Johan Alkstål over 3 years
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, thescope.$watch
in the directive isn't called.Any ideas why?
-
Michael Benford over 10 yearsFWIW, you can also assign the factory to the scope and then use
$watch
with a string expression. -
Johan Alkstål over 10 yearsPlease do share what you mean, Michael. It's always good to see alternatives.