Access parent controller data from main controller

时间:2015-06-26 09:47:31

标签: angularjs

I have the following MainController:

function MainController($scope, DataService) {

  $scope.model = {
    data: null
  }

  $scope.init = function () {
    DataService.GetById(2)
      .success(function (data, status, headers, config) {        
         $scope.model.data = data;
      })
  };

  $scope.init();

} 

I then have a child controller where I need to access the parent scope:

function ChildController($scope) {

  $scope.model = {
    data: null
  }

  $scope.init = function () {
    #scope.model.data = $scope.$parent.model.data;
  };

  $scope.init();

}  

I get an error saying $scope.$parent.model.data is null.

If I check the console $scope.$parent.model.data seems null but if I click it I see that it is not and it has the correct data ...

I believe the problem is I am defining the data in ChildController before it has been defined in the MainController due to DataService.GetById which queries the database ...

Am I right?

How can I solve this?

2 个答案:

答案 0 :(得分:2)

You are right: the problem you have, is that your parent controller populates "data" inside a promise.

To understand what a promise is, you can check this : https://docs.angularjs.org/api/ng/service/$q

When your child controller is run, the promise will certainly not have returned yet.

The first way to handle that is adding a watch :

function ChildController($scope) {

  $scope.model = {
    data: null
  }

  $scope.init = function () {
    //$scope.model.data = $scope.$parent.model.data;
   var watchRemover = $scope.$watch('$parent.model.data', function(newVal, oldVal){
        if (newVal !== oldVal && newVal !== null){
           $scope.model.data = $scope.$parent.model.data;
           watchRemover();
        }
   })
  };

  $scope.init();

} 

Another solution is to handle it with events :

Parent controller :

 DataService.GetById(2)
  .success(function (data, status, headers, config) {        
     $scope.model.data = data;
     $scope.$broadcast("data loaded");
  });

child controller :

$scope.$on("data loaded", function(){
     $scope.model.data = $scope.$parent.model.data;
});

答案 1 :(得分:1)

While setting up watches or using broadcast/edit is fine, I think a simpler solution would be binding one level upper.

Change $scope.model.data = $scope.$parent.model.data; to $scope.model= $scope.$parent.model;

In this bind whenever $scope.$parent.model.data change, it will also be reflected in $scope.model.data. Be careful the reverse is also true, though.

Edit: On second thought, this approach won't help OP if he's not handling null correctly in the child controller, or else the original code would have worked. My approach is useful when $scope.$parent.model.data changes, it will be automatically available in child.