5

I have an AngularJS controller which loads data from a service (doing asynchronous $http requests).

And in a child controller, I need to wait for this data to be loaded before I can do another $http request to load some more detailed information.

I tried doing this in the child controller :

$scope.$parent.watch('dataLoaded', function(dataLoaded) {
  if (dataLoaded) {
    // call the service doing the subsequent $http request with data from parent controller
  }
};

When I do this, it works in the child controller, but it seems like the 'dataLoaded' variable (which goes from false to true once data is loaded in parent controller) never have its value actually changed to true in the parent controller.

What am I doing wrong ? Should I use a completely different approach?

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
Hexalyse
  • 369
  • 1
  • 4
  • 14
  • seems like `$broadcase/$emit` issue. – Jai Oct 27 '15 at 12:55
  • @Jai Indeed, I thought about using event broadcasting. But I wondered if it was a good approach, and that maybe I was doing something wrong all together. – Hexalyse Oct 27 '15 at 13:01

1 Answers1

5

The point here is - we need a reference to be watched (a dot in the name). E.g. Model: {}

So, in parent state/view we would declare it

$scope.Model = {
   dataLoaded: false,
};

And child view can $watch that model property changes (but not on parent, just on current scope)

$scope.$watch('Model.dataLoaded', function(dataLoaded) {
  if (dataLoaded) {
      ...
  }
});

See more details here:

How do I share $scope data between states in angularjs ui-router?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • I tried doing this, the parent controller is working fine, but the watcher in the child controller is never fired, as opposed to before with a simple $scope.dataLoaded = false; declaration (it worked, but when I added the watch in the child controller, parent variable value weren't updated anymore !) – Hexalyse Oct 27 '15 at 13:09
  • I adjusted my answer... we should always $watch current scope. If you follow my link and view inheritance, then Model.someProperty will work for you.. hope it helps – Radim Köhler Oct 27 '15 at 13:10
  • 1
    Ohoh... Now I'm ashamed. In fact, it works as good without using $scope.Model.variable (and just $scope.variable), but I just forgot the "$" in front of "watch"... We'll say it's the fatigue ! – Hexalyse Oct 27 '15 at 13:16
  • Yes, $watch is the essence ;) Good luck with UI-Router *(my suggestion would be, try to think also about introducing Model rather then $watching parent $scope in child. It could later bring lot of issues with complexity and maintenance... just suggestion)* – Radim Köhler Oct 27 '15 at 13:19
  • Ok, thank you for your advice. Isn't it related to the types of watches ? (reference, collection, equality) ? – Hexalyse Oct 27 '15 at 13:21
  • I'd say it is related to reference watches, in case, that we will `$watch` child **$scope**. Then we need a reference `Model : {}` like solution. Because that will be shared among all the states in our hierarchy tree... ValueTypes (e.g. boolean) as opposed to ReferenceTypes are just copied during child $scope creation.. and won't be changed later... hope it helps a bit – Radim Köhler Oct 27 '15 at 13:24