Join the Stack Overflow Community
Stack Overflow is a community of 6.3 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I've set up my controllers using data-ng-controller="xyzController as vm"

I have a scenario with parent / child nested controllers. I have no problem accessing parent properties in the nested html by using $parent.vm.property, but I cannot figure out how to access the parent property from within my child controller.

I've tried injecting $scope and then using $scope.$parent.vm.property, but this isn't working?

Can anyone offer advice?

share|improve this question
    
Can you post some code here, the parent and child controllers ? – Jayantha Lal Sirisena Jan 30 '14 at 10:43
    
it would be great if you can set up on jsfiddle – Anand Jan 30 '14 at 11:00
1  
I've updated my answer, probably this describes better what you were looking for. – Dieterg Mar 27 '14 at 8:18
up vote 481 down vote accepted

If your HTML is like below you could do something like this:

<div ng-controller="ParentCtrl">
    <div ng-controller="ChildCtrl">
    </div>
</div>

Then you can access the parent scope as follows

function ParentCtrl($scope) {
    $scope.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentcities = $scope.$parent.cities;
}

If you want to access a parent controller from your view you have to do something like this:

<div ng-controller="xyzController as vm">
   {{$parent.property}}
</div>

See jsFiddle: http://jsfiddle.net/2r728/

Update

Actually since you defined cities in the parent controller your child controller will inherit all scope variables. So theoritically you don't have to call $parent. The above example can also be written as follows:

function ParentCtrl($scope) {
    $scope.cities = ["NY","Amsterdam","Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentCities = $scope.cities;
}

The AngularJS docs use this approach, here you can read more about the $scope.

Another update

I think this is a better answer to the original poster.

HTML

<div ng-app ng-controller="ParentCtrl as pc">
    <div ng-controller="ChildCtrl as cc">
        <pre>{{cc.parentCities | json}}</pre>
        <pre>{{pc.cities | json}}</pre>
    </div>
</div>

JS

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl() {
    var vm = this;
    ParentCtrl.apply(vm, arguments); // Inherit parent control

    vm.parentCities = vm.cities;
}

If you use the controller as method you can also access the parent scope as follows

function ChildCtrl($scope) {
    var vm = this;
    vm.parentCities = $scope.pc.cities; // note pc is a reference to the "ParentCtrl as pc"
}

As you can see there are many different ways in accessing $scopes.

Updated fiddle

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}
    
function ChildCtrl($scope) {
    var vm = this;
    ParentCtrl.apply(vm, arguments);
    
    vm.parentCitiesByScope = $scope.pc.cities;
    vm.parentCities = vm.cities;
}
    
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<div ng-app ng-controller="ParentCtrl as pc">
  <div ng-controller="ChildCtrl as cc">
    <pre>{{cc.parentCities | json}}</pre>
    <pre>{{cc.parentCitiesByScope | json }}</pre>
    <pre>{{pc.cities | json}}</pre>
  </div>
</div>

share|improve this answer
1  
See updated answer – Dieterg Mar 27 '14 at 8:05
3  
I think the two issues with your last update is 1. Inheriting the parent scope can have potential namespace conflicts, and 2. Requires knowledge that parent controller alias is 'pc'. This makes re-use more difficult. – tchen Jul 31 '14 at 15:52
2  
You defined controllers as function CtrlName(...){} but how can we achieve that using Angular nomenclature? like : angular.module(MdlName).controller(CtrlName, function(...){}); – Pedro Justo Dec 3 '14 at 15:12
1  
sorry, you are right! In the 'controller as' method, using '$scope.pc.cities;' to access parent's cities seems to me a 'step back' because if in childCtrl we don't have the property 'cities' it will auto access parent's cities. There is no other way to solve this problem? – Pedro Justo Dec 3 '14 at 17:12
1  

I've just checked

$scope.$parent.someProperty

works for me.

and it will be

{{$parent.someProperty}}

for the view.

share|improve this answer
    
hmmm, not working for me. Wonder if it has to do with the controller as vm syntax. – zpydee Jan 30 '14 at 11:24

Some times you may need to update parent properties directly within child scope. e.g. need to save a date and time of parent control after changes by a child controller. e.g Code in JSFiddle

HTML

<div ng-app>
<div ng-controller="Parent">
    event.date = {{event.date}} <br/>
    event.time = {{event.time}} <br/>
    <div ng-controller="Child">
        event.date = {{event.date}}<br/>
        event.time = {{event.time}}<br/>
        <br>
        event.date: <input ng-model='event.date'><br>
        event.time: <input ng-model='event.time'><br>
    </div>
</div>

JS

    function Parent($scope) {
       $scope.event = {
        date: '2014/01/1',
        time: '10:01 AM'
       }
    }

    function Child($scope) {

    }
share|improve this answer

When you are using as syntax to define a controller then to access parent scope variable in child controller use following :

var id = $scope.parentCtrl.id;

Where parentCtrl is name of parent controller using as syntax and user is a variable defined in same controller.

share|improve this answer

I believe I had a similar quandary recently

function parentCtrl() {
   var pc = this; // pc stands for parent control
   pc.foobar = 'SomeVal';
}

function childCtrl($scope) {

   // now how do I get the parent control 'foobar' variable?
   // I used $scope.$parent

   var parentFoobarVariableValue = $scope.$parent.pc.foobar;

   // that did it
}

My setup was a little different, but the same thing should probably still work

share|improve this answer

Perhaps this is lame but you can also just point them both at some external object:

var cities = [];

function ParentCtrl() {
    var vm = this;
    vm.cities = cities;
    vm.cities[0] = 'Oakland';
}

function ChildCtrl($scope) {
    var vm = this;
    vm.cities = cities;
}

The benefit here is that edits in ChildCtrl now propogate back to the data in the parent.

share|improve this answer

You can also circumvent scope inheritance and store things in the "global" scope.

If you have a main controller in your application which wraps all other controllers, you can install a "hook" to the global scope:

function RootCtrl($scope) {
    $scope.root = $scope;
}

Then in any child controller, you can access the "global" scope with $scope.root. Anything you set here will be globally visible.

Example:

function RootCtrl($scope) {
  $scope.root = $scope;
}

function ChildCtrl($scope) {
  $scope.setValue = function() {
    $scope.root.someGlobalVar = 'someVal';
  }
}

function OtherChildCtrl($scope) {
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app ng-controller="RootCtrl">
  
  <p ng-controller="ChildCtrl">
    <button ng-click="setValue()">Set someGlobalVar</button>
  </p>
  
  <p ng-controller="OtherChildCtrl">
    someGlobalVar value: {{someGlobalVar}}
  </p>

</div>

share|improve this answer
    
This doesn't really scale. It's like defining global variables that must be unique across many files/contexts. – ZachB Dec 5 '15 at 0:38

In the chosen answer (in the controller as case) above I noted one thing.

When you use the .apply() method, you are calling the ParentCtrl function with this being the vm of the child controller.

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl() {

    var vm = this;
    ParentCtrl.apply(vm, arguments); // Inherit parent control

    vm.parentCities = vm.cities;
}

vm.cities will be available in the child controller but it will a copy of the vm.cities of the parent. It won't be updated in case vm.cities changes in the parent.

if you do:

function ChildCtrl($scope) {

    var vm = this;
    vm.parentCities = $scope.pc.cities; 
}

vm.parentCities is a ref to vm.cities in the parent. So changes will be in the child and parent.

Using a constructor you can do:

function ChildCtrl($scope) {

    var vm = this;
    vm.parent = Object.create($scope.pc); 
}

vm.cities will be updated in the child controller if it changes in the parent but if it gets overridden in the child, then it won't affect the parent.

In my case I needed this last approach as I wanted to share a parent object to many controllers without creating a shared reference to the parent object.

Here is a plunker http://plnkr.co/edit/EJoQuz2aXIB6i4FVzY2U?p=preview

share|improve this answer

protected by Pankaj Parkar Jan 21 at 20:43

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.