Chris Bier
Chris Bier

Reputation: 14447

AngularJS - Child controller private scope (preventing inheritance)

I have a case where I need to nest controllers. I do not want the child scope to inherit from the parent scope because I have scope variables with the same names in both controllers. Is there a way to do this?

I am trying to prevent the childController's variable from being updated when the parentController's variable is changed.

<div ng-controller="parentController">
     {{myVariable}}
     <div ng-controller="childController">
          {{myVariable}}
     </div>
</div>

I am aware that I can change the name of the child controller's scope variable to avoid the inheritance problem completely, but I am looking for an alternative. Is there any known way to do this?

Kind of like isolating the scope of a directive, but isolated or private controller scope.

Edit: I have discovered that the child controller will inherit the parent controller scope var value when there is no default value for that var set in the child controller.

Compare: http://jsfiddle.net/4qcqdb6z/ to http://jsfiddle.net/4qcqdb6z/2/

Upvotes: 2

Views: 1403

Answers (3)

Wilco
Wilco

Reputation: 1093

A way to achieve this is to use Object.defineProperty in the child controller

.controller('childController',  ['$scope', function($scope){
    Object.defineProperty($scope, 'myVariable', { value: 'childControllerValue', writable: true });
}])

This will create a variable myVariable on the child scope that can be set independently of a variable with the same name on the parent scope.

Angular inheritance works because the parent scope is the prototype of the child scope, so if in your child scope you try to access or assign to $scope.myVariable , javascript internally looks back up the prototype chain and actually accesses $scope.__proto__.myVariable. By defining a new property directly on the object you mask this inherited property, allowing independent values.

This works when using {{myVariable}} in the view. I've tested it with watchers as well, which will watch the variable that is on their scope, not a parent or child version of it. See https://plnkr.co/edit/mXLNGAGc0q8T36DV43aK for some testing.

Upvotes: 0

Aral Roca
Aral Roca

Reputation: 5919

Try this:

<div ng-controller="parentController as parent">
     {{parent.myVariable}}
     <div ng-controller="childController as child">
          {{child.myVariable}}
     </div>
</div>

In the controllers:

.controller('childController',  [, function(){
     var vm = this; // You can use now vm like $scope
}])

Upvotes: 0

Amin Mohamed Ajani
Amin Mohamed Ajani

Reputation: 294

I just had this problem while developing my own form. I came here to find no response. So I figured it out myself. So for your code,

<div ng-controller="parentController">
     {{myVariable}}
     <div ng-controller="childController">
          {{myVariable}}
     </div>
</div>

your child controller should include a scope:{}

.controller('childController',  ['$scope', function($scope){
 scope:{}; //this prevents it from inheriting the parent scope variables
}])

I know the answer is pretty late but hope those who come across this from now find it helpful

Upvotes: 1

Related Questions