I have a NavbarCtrl that is outside of ng-view. I have a login controller that talks to a service to get a user logged in. Once the user is logged in, I want the Navbar to update with the user's email address. However for the life of me, I can't seem to get the Navbar scope to update with the data that is loaded in to my "Auth" service once the user is logged in.
This is my main index.html:
<div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar-inner"> <div class="container"> <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <a class="brand" href="#">Brim</a> <div class="pull-right" ng-controller="NavbarCtrl"> <div ng-click="refresh()">hello</div> {{ user.email }} </div> </div> </div> </div> <div class="container" ng-view>
And my service:
.factory('Auth', function($resource) { var authenticated = false; var user = {}; return { isAuthenticated: function () { return authenticated; }, getUser: function() { return user; }, login: function(loginUser, callback) { user = {email:'[email protected]'} authenticated = true; callback(true); //actual code for logging in taken out for brevity } } })
And my Login and Navbar controllers:
function LoginCtrl($scope, $location, Auth) { $scope.login = function() { Auth.login($scope.user, function(success) { if(success) $location.path('/dashboard'); //console.log(Auth.getUser()) }); } } function NavbarCtrl($scope, Auth) { //thought this should work $scope.user = Auth.getUser(); //experimenting unsuccessfully with $watch $scope.$watch(Auth.isAuthenticated(),function () { $scope.user = Auth.getUser() }) //clicking on a refresh button is the only way I can get this to work $scope.refresh = function() { $scope.user = Auth.getUser() } }
From my research I would have thought that $scope.user = Auth.getUser(); would work, but it's not and I'm at a complete loss as to how how I can get my Navbar updated when a user is logged in. Thanks in advance for any help.
Update: well, you learn something new every day... just remove the ()
to watch the results of a function:
$scope.$watch(Auth.isAuthenticated, function() { ... });
Updated fiddle
In this fiddle, notice how 'watch1' and 'watch3' both trigger a second time when the value of $scope.isAuthenticated
changes.
So, this is the general technique to watch for changes to a primitive value that is defined on a service:
To watch for changes to an object or array that is defined on a service:
user = ...;
angular.copy(newInfo, user)
or this: user.email = ...
Example:
$scope.user = Auth.getUser(); // Because user is a reference to an object, if you change the object // in the service (i.e., you do not reassign it), $scope.user will // likewise change. $scope.$watch('user', function(newValue) { ... }, true); // Above, the 3rd parameter to $watch is set to 'true' to compare // equality rather than reference. If you are using Angular 1.2+ // use $watchCollection() instead: $scope.$watchCollection('user', function(newValue) { ... });
Original answer:
To watch the results of a function, you need to pass $watch a function that wraps that function:
$scope.$watch( function() { return Auth.isAuthenticated() }, function() { ... });
Fiddle. In the fiddle, notice how only 'watch3' triggers a second time when the value of $scope.isAuthenticated
changes. (They all trigger initially, as part of $watch initialization.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With