I'll preface this with the fact that I really have no idea if this is the best way to achieve what I'm doing and I'm very open to better suggestions.
I've got a user account system using OAUTH2
which gets looks up user info in my database and saves it as a variable, $rootScope.userInfo
. This resides in a controller which is appended to my app's body
; here I was thinking that the highest-level controller would load before those that live within it, but apparently not.
If I load a view which tries to access this $rootScope.userInfo
object before my mainCtrl
has had a chance to load it in from my database, it throws a javascript error and Angular
breaks.
For reference, here's a rough idea of the template:
<body ng-controller="mainCtrl">
<header>Content</header>
<div class='main-view' ng-controller="userProfile">
<p>{{user.name}}</p>
<p>{{user.email}}</p>
</div>
</body>
I'm loading $rootScope.userInfo
in mainCtrl
like this:
$http.get('/api/users/' + $cookies.id).
success(function(data) {
$rootScope.userInfo = data.user[0];
console.log("User info is:");
console.log($rootScope.userInfo);
$scope.status = 'ready';
});
Then for my userProfile
control, I do:
function userProfile($scope, $cookies, $http, $routeParams, $rootScope){
if($scope.status == 'ready'){
$scope.user = $rootScope.userInfo;
console.log("Double checking user info, here it is:");
console.log($rootScope.userInfo);
}
}
If I'm coming from a different page in the app which doesn't call on $rootScope.userInfo
, the API has enough time to look it up and my userProfile
page works fine. However if doing a full-page refresh, the $rootScope.userInfo
doesn't have time to load and I get errors.
How can I fix this?
The problem you describe is one of the reasons why it is not recommended to share data between controllers using $rootScope
: it creates a manual "invisible" dependency between two controllers, that you have to manually fix when the end user hasn't gone through the other controller yet.
The recommended solution is to move the user loading logic into a service, say userProfileService
, which you inject into both controllers that need it. It will then be created once, and used for both controllers. In such a service you could load the user profile with $http
when a controller asks for it, and return it from cache when the next one does. This way, the dependency goes from both controllers to a shared service, rather than from one controller to another.
I'm not a huge fan of the AngularJS documentation, but these might help: DI, Creating Services, and Injecting Services.
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