2

I am using controllerAs syntax in my application, I want to access parent controller's function from child controller, I know this is achievable by injecting $scope, however considering Angular has tried so hard to get rid of the $scope from code, I'd like to know if there is a more elegant way of doing this without injecting $scope?

Here's an example of HTML:

<div ng-controller="AppCtrl as app">
  <div ng-controller="ChildCtrl as child">
  </div>
</div>

And corresponding controllers:

angular.module('test').controller('AppCtrl', function () {
  var vm = this;
  vm.log = function() {
    console.log("Output");
  }
}  

angular.module('test').controller('ChildCtrl', function () {
  var vm = this;
  // Here I want to access parent's log() function
}  

I know I can inject $scope and then access the log function by $scope.app.log(), but is there a bettter way to access log without injecting the $scope?

doranT
  • 167
  • 3
  • 11
  • Possible duplicate of [angularjs Access parent scope from child controller](http://stackoverflow.com/questions/21453697/angularjs-access-parent-scope-from-child-controller) – Ted Aug 17 '16 at 18:23

2 Answers2

3

One option would be to use Angular 1.5 components (docs).

It would look something like this in child component:

.component('childComponent', {
  require: {
    parentCtrl: '^ parentCtrl'
  }
  controller: function() {
    this.parentCtrl.anyMethod(); //here we are accessing parent's controller properties
  }

  ...

});
Ruben Helsloot
  • 12,582
  • 6
  • 26
  • 49
oKonyk
  • 1,468
  • 11
  • 16
1

This answer is being posted about 6 months after the question was asked but I think it may be helpful to other visitors to check the solutions I propose below.

Angular controllers have prototypal inheritance, which means the $scope object of the parent controller is accessible by the children. If instead of binding your properties and methods to $scope you use the this keyword and controller as syntax, children's $scope will not have direct access to the parent's members but you can still access them via $scope.$parent.

That said, there are two possible (clean and easy) ways to solve your problem:

1) You can bind properties and methods to the $scope object of your parent controller and have direct access to them via $scope in any child controller (and you can overwrite properties/methods if you want--like you would on a regular Class). So if you define

$scope.log = function() { console.log("output") } 

on your parent controller, your child controller has access to it by simply calling $scope.log(). Check this fiddle.

2) Or, since you are using the this keyword and controller as syntax to bind the controllers to the views, the child's $scope object will not have direct access to the parent's properties and methods because these are not members of the parent's $scope but of this, the instance of the parent controller itself. In this scenario, you should access the parent via $scope.$parent. Among other things, "app" (the alias you created for "AppCtrl", thus the instance of that controller itself) will be a property of $scope.$parent. Since you defined the "log" method as a member of the controller itself and not its $scope object, "log" is a member of "app" and your child controller can access the parent's "log" method as such: $scope.$parent.app.log(). Check this fiddle

Here is some further reading on this topic: https://github.com/angular/angular.js/wiki/Understanding-Scopes

Gabriel Ferraz
  • 592
  • 6
  • 26