0

So the structure of my controller may be to blame for this. Here you can see the parent and child controllers, but the important parts are here :

Parent Controller

//Load version
$scope.person = People.people.get({ id: $routeParams.id}, function(person) {
     var associations = {
         events: person.events || [],
         people: person.people || [],
         places: person.places || []
     };
     $scope.$broadcast('setAssociations', associations);
});
//Event version
$scope.$on('getAssociations', function(e, args) {
  var associations = {
    events: $scope.person.events || [],
    people: $scope.person.people || [],
    places: $scope.person.places || []
  };
  $scope.$broadcast('setAssociations', associations);
});

Child Controller

$scope.$on('setAssociations', function(event, args) {
    $scope.parentEvents = args.events;
});

$scope.$emit('getAssociations', {});

The idea is that I need to get the events from the parent's person object down to the child controller. The problem is, each method of raising setAssociations from the parent only works in one context.

The load version works if the page is navigated to from within the app (hash, navigation). However, when reloading or navigating from outside (full load), the child event is never raised, presumably because it hasn't registered its listeners yet.

The event version works if the page is refreshed, or navigated to from outside the app (anything causing the page to fully load). When navigated to, the $scope is empty though, and this method fails.

So the order in which the app loads the controllers is different when "deep-linking" or refreshing, and when doing internal navigation. How can I get consistent load behavior from angular controllers that have a parent child relationship?

Kyeotic
  • 19,697
  • 10
  • 71
  • 128

1 Answers1

5

Looking at the problem from a different perspective, since child scopes prototypically inherit from parent scopes, this means that any properties we define on a parent scope are immediately accessible in the child scope... even if you add properties to the parent scope later, after the child scope is created. In other words, you might not have to use an event to get the information you want to the child.

If your problem is simply that the child scope needs some information from the parent scope, just assign that data to a new parent $scope property, and have your child view access it. When it becomes defined, it will appear in the child view. Instead of var associations, try $scope.associations.

Here is a contrived fiddle that uses an ng-click to add some data to a parent scope, which then becomes visible in the child view.

Does this solve your problem?

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Yes, thank you this is much better than what I was doing. I didn't see this anywhere in the angular tutorial or the overview! This is such a perfect technique, why don't they tell you about it? – Kyeotic Dec 12 '12 at 17:27
  • 2
    Well, I should have mentioned that sharing data this way is not a 'best practice', since this way assumes a particular parent-child DOM structure. If you someday decide to make the child a peer rather than a child, this technique fails. The preferred technique is to create a service and have the parent and child controllers inject that service -- function MyCtrl($scope, myService) -- and the shared data is stored into and accessed from the service. Example fiddle: http://jsfiddle.net/whnSs/ – Mark Rajcok Dec 12 '12 at 17:35
  • See also http://stackoverflow.com/questions/12008908/pass-variables-between-controllers – Mark Rajcok Dec 12 '12 at 17:39