1

I'm using ui-router for my application and nesting controllers within ui-view. My parent controller looks like this:

'use strict';

angular.module("discussoramaApp").controller("mainController", ["RestFullResponse", "Restangular", "localStorageService", "$scope", function(RestFullResponse, Restangular, localStorageService, $scope){

  var currentId = localStorageService.get("***");

  var user = Restangular.one("users", currentId);
  var Profile = user.get({}, {"Authorization" : localStorageService.get('***')}).then(function(profile) {
    $scope.profile = profile;
  });

}]);

And my child controller:

'use strict';

angular.module("discussoramaApp").controller("getTopicsController", ["RestFullResponse", "Restangular", "localStorageService", "$scope", function(RestFullResponse, Restangular, localStorageService, $scope){

  var topics = Restangular.all('topics');
  var allTopics = topics.getList({},{"Authorization" : localStorageService.get('***')}).then(function(topics){
    $scope.topics = topics;
  });

  console.log($scope); // this works
  console.log($scope.profile); // this returns undefined

}]);

The problem I'm having is getting the inherited $scope value for profile in the child controller. When I log $scope, profile is clearly visible in the console.

$scope console log

But when I try to log $scope.profile the console returns undefined. Any ideas?

Edit: Adding my ui-router config.

angular.module("discussoramaApp").config(
  function($stateProvider, $urlRouterProvider){
    $urlRouterProvider.otherwise('/home');
    $urlRouterProvider.when('', '/home');

    $stateProvider

      .state('main',{
        url: '',
        templateUrl: 'partials/main.html',
        requireLogin: true
      })

      .state('main.home',{
        url: '/home',
        templateUrl: 'partials/main.home.html',
        requireLogin: true,
        title: 'Home'
      });

  }
);

And the corresponding html files:

// main.html
<div ng-controller="mainController">

  <div class="container">
    <div ui-view></div>
  </div>

</div>

and the child html partial:

// main.home.html
<div ng-controller="getTopicsController">
  <div ng-repeat="topic in topics | filter:search">
    <a ui-sref="main.topic({id: topic.id})">{{ topic.topic_title }}</a>
  </div>
</div>

UPDATE: Solved this with a watcher set up like this in the child controller. Thanks @jonathanpglick and @Nix for the help.

$scope.$watch('profile', function(profile) {
  if(profile) {
    $window.document.title = "Discussorama | " + profile.user.name;
  }
});
2
  • Please post a blub that shows you ui-router config. Commented Apr 29, 2014 at 20:46
  • Added ui-router config and partials. Commented Apr 29, 2014 at 20:52

2 Answers 2

2

$scope.profile is being set after an asynchronous request so I suspect that the second controller is being instantiated before user.get() returns and assigns a value to $scope.profile.

I think you'll want to set up a watcher (like $scope.$watch('profile', function(profile) {});) in the child controller so you can do things when the profile becomes available or changes.

Also, the reason you can see the profile key on $scope when you console log $scope can be explained here: https://stackoverflow.com/a/7389177/325018. You'll want to use console.dir() to get the current state of the object when it's called.

UPDATE:

I just realized you're using the ui-router and so there's an even easier way to do this. The ui-router has a resolve object that you can use to dependency inject things like this into your controller. Each resolve function just needs to return a value or a promise and it will be available for injection into the controller with resolve key name. It would look like this for you:

angular.module("discussoramaApp").config(
  function($stateProvider, $urlRouterProvider){
    $urlRouterProvider.otherwise('/home');
    $urlRouterProvider.when('', '/home');

    $stateProvider

      .state('main',{
        url: '',
        templateUrl: 'partials/main.html',
        requireLogin: true,
        resolve: {
          profile: ['Restangular', 'localStorageService', function(Restangular , localStorageService) {
            var currentId = localStorageService.get("***");
            var user = Restangular.one("users", currentId);
            return user.get({}, {"Authorization" : localStorageService.get('***')});
          }
        }
      })

      .state('main.home',{
        url: '/home',
        templateUrl: 'partials/main.home.html',
        requireLogin: true,
        title: 'Home'
      });

  }
);

angular.module("discussoramaApp").controller("mainController", ["profile", "$scope", function(profile, $scope){
  $scope.profile = profile;
}]);
Sign up to request clarification or add additional context in comments.

4 Comments

Ah thanks, I'm still a bit lost with watch and resolve. But I got it working. Need to read up on $scope in the docs a bit more I guess.
Hmm, I'm still having an issue with the watch. I know this is the right way to go just not sure how to implement it. I added some code to the end of my question to see if I'm doing it right.
I set up a watcher but I'm getting an error thrown. Could you take a look and see what the problem could be.
Yeah, I forgot to mention that initially the profile value will come in as null.
1

Just because you have nested scope, doesn't mean it will wait for user.get() to return before instantiating your nested getTopicsController.

Your issue is:

  1. mainController controller initializes and calls user.get()
  2. getTopicsController initializes and logs console.log($scope.profile)
  3. The call to user.get() returns and then sets on scope.

This is a common issue, if you need to gaurantee that $scope.profile is set, use resolve or watch the variable.

I actually gave an example of how to do this earlier today: AngularJS $rootScope.$broadcast not working in app.run

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.