Reputation: 2220
I have a variable set to true in the $rootScope
. This variable is named loggedIn
.
I created a NavController to control the display of my main menu links, and as you can see I injected the $rootScope
properly.
appControllers.controller("NavController", function($rootScope, $scope) {
console.log($rootScope); //We can see that loggedIn is true
console.log($rootScope.loggedIn); //Outputs false
//Not working as expected
if($rootScope.loggedIn === true){
$scope.showHomeMenu = false;
$scope.showGameMenu = true;
$scope.currentHome = '/lobby';
}
else {
$scope.showHomeMenu = true;
$scope.showGameMenu = false;
$scope.currentHome = '/login';
}
});
Oddly, this doesn't work because $rootScope.loggedIn
is evaluated to false
, even though it's value was set to true
. This is the output I get from the console.
As you can see from the $rootScope
output, loggedIn
should be true
. But it's evaluated to false
in the controller.
I guess I'm doing something really dumb here, but I can't figure out why!!
Edit 2
@rvignacio pointed out something interesting. The object $rootScope
I see is the state of the object at the time of the expansion, not the state at the moment when I call log().
(which was predictable...)
I guess the issue is deeper than I thought! I'll have to dig to find the bug!
Edit
I set loggedIn in run()
.
app.config(function($routeProvider, $httpProvider) {
$routeProvider.
when('/', {
...
}).
...
});
var interceptor = ['$rootScope', '$q',
function(scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) {
var deferred = $q.defer();
var req = {
config: response.config,
deferred: deferred
};
scope.$broadcast('event:loginRequired');
return deferred.promise;
}
// otherwise
return $q.reject(response);
}
return function(promise) {
return promise.then(success, error);
};
}
];
$httpProvider.responseInterceptors.push(interceptor);
}).run(['$rootScope', '$http', '$location',
function(scope, $http, $location) {
/**
* Holds page you were on when 401 occured.
* This is good because, for example:
* User goes to protected content page, for example in a bookmark.
* 401 triggers relog, this will send them back where they wanted to go in the first place.
*/
scope.pageWhen401 = "";
scope.loggedIn = false;
scope.logout = function() {
$http.get('backend/logout.php').success(function(data) {
scope.loggedIn = false;
scope.$broadcast('event:doCheckLogin');
}).error(function(data) {
scope.$broadcast('event:doCheckLogin');
});
};
scope.$on('event:loginRequired', function() {
//Only redirect if we aren't on restricted pages
if ($location.path() == "/signup" ||
$location.path() == "/login" ||
$location.path() == "/contact" ||
$location.path() == "/about")
return;
//go to the login page
$location.path('/login').replace();
});
/**
* On 'event:loginConfirmed', return to the page.
*/
scope.$on('event:loginConfirmed', function() {
//*********************
//THIS IS WHERE I SET loggedIN
//*********************
scope.loggedIn = true;
console.log("Login confirmed!");
$location.path('/lobby').replace();
});
/**
* On 'logoutRequest' invoke logout on the server and broadcast 'event:loginRequired'.
*/
scope.$on('event:logoutRequest', function() {
scope.logout();
});
scope.$on("$locationChangeSuccess", function(event) {
//event.preventDefault();
ping();
});
scope.$on('event:doCheckLogin', function() {
ping();
});
/**
* Ping server to figure out if user is already logged in.
*/
function ping() {
$http.get('backend/checksession.php').success(function() {
scope.$broadcast('event:loginConfirmed');
}); //If it fails the interceptor will automatically redirect you.
}
//Finally check the logged in state on every load
ping();
}
]);
Upvotes: 0
Views: 1678
Reputation: 2220
You guys were right. I'm using async calls to set loggedIn to true, so it was all a question of timing.
Welcome to the world of aynschronism dear me.
$watch
-ing loggedIn
solved the issue.
appControllers.controller("NavController", function($rootScope, $scope) {
$scope.showHomeMenu = true;
$scope.showGameMenu = false;
$scope.currentHome = '/login';
//ADDED
$rootScope.$watch('loggedIn', function(){
console.log($rootScope.loggedIn);
if($rootScope.loggedIn === true){
$scope.showHomeMenu = false;
$scope.showGameMenu = true;
$scope.currentHome = '/lobby';
}
else {
$scope.showHomeMenu = true;
$scope.showGameMenu = false;
$scope.currentHome = '/login';
}});
});
Also I changed where I set loggedIn to false in my code to increase performance and remove visible latency when logging out. Now everything runs fast.
Upvotes: 1