Reputation: 325
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.
Upvotes: 24
Views: 21515
Reputation: 3594
Using user
as your variable name is generally not a good idea. I once I changed it ti currentUser
everything worked for me.
Upvotes: 0
Reputation: 364677
Update: well, you learn something new every day... just remove the ()
to watch the results of a function:
$scope.$watch(Auth.isAuthenticated, function() { ... });
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.)
Upvotes: 54
Reputation: 4211
Try to change
$scope.$watch(Auth.isAuthenticated(),function () { $scope.user = Auth.getUser() })
to
$scope.$watch(Auth.isAuthenticated(),function () { $scope.user = Auth.getUser() }, true)
Look at the AungularJs $watch documentation for a detailed explanation, the default value is false which means that Angular detects changes in the first parameter values by reference, while passing true means the check is done by equality. Being the parameter a function, the check returns always false, since the reference to the function is always the same.
Upvotes: 0