Ensuring loading one AngularJS controller before another

I will talk about this with the fact that I really do not know if this is the best way to achieve what I am doing, and I am very open to the best offers.

I have a user account system using OAUTH2 that searches for user information in my database and saves it as the $rootScope.userInfo variable. This is in the controller, which is being added to my body application; here I thought that the top-level controller would boot up to those who live inside it, but apparently not.

If I load a view that tries to access this $rootScope.userInfo object before my mainCtrl ability to load it from my database, it will throw a javascript and Angular breaks error.

For reference, here is a rough idea for a 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 load $rootScope.userInfo in mainCtrl as follows:

 $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 do the following:

 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 come from another page in an application that does not call $rootScope.userInfo , the API has enough time to view it, and my userProfile page userProfile working fine. However, if you are performing a full page update, $rootScope.userInfo does not have time to load, and I get errors.

How can i fix this?

+6
source share
2 answers

The problem you are describing is one of the reasons why it is not recommended to exchange data between controllers using $rootScope : it creates a manual “invisible” relationship between the two controllers, which you must manually fix when the end user hasn not yet passed through another controller.

The recommended solution is to move the user load logic to the service, say userProfileService , which you enter into both controllers that need it. Then it will be created once and will be used for both controllers. In such a service, you can load the user profile using $http when the controller requests it, and return it from the cache when the next one does. Thus, the dependency goes from both controllers to a common service, and not from one controller to another.

I'm not a big fan of AngularJS documentation, but they can help: DI , Service Creation, and Injection Services .

+14
source

Use then instead of success and delay loading the child controller with ng-include :

 <body ng-controller="mainCtrl"> <header>Content</header> <ng-include src="templatePath"></ng-include> </body> 

Move the HTML inside the new userprofile.html template:

 <div class='main-view' ng-controller="userProfile"> <p>{{user.name}}</p> <p>{{user.email}}</p> </div> 

Callback inside mainCtrl:

 $http.get('/api/users/' + $cookies.id). then(function(data) { /* mainCtrl being the parent controller, simply exposing the properties to $scope would make them available to all the child controllers.*/ $rootScope.userInfo = data.user[0]; /* assign the template path to load the template and instantiate the controller */ $scope.templatePath = "userprofile.html"; }); 
0
source

Source: https://habr.com/ru/post/952261/


All Articles