Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance for scopes in AngularJS

Tags:

angularjs

In a parent controller scope, I have defined selectedItem which is set to 'x'. Then in the child scope, I have defined selectedItem using ngModel:

<div ng-app>
  <div ng-controller="CtrlA">
       <div ng-controller="CtrlB">
         <select ng-model="selectedItem" ng-options="item for item in items">
         </select>
      </div>
  </div>
</div>

function CtrlA($scope) {
    $scope.selectedItem = 'x';
    $scope.items = ['x', 'y'];
}

function CtrlB($scope) {}

When the page is loaded, the selectedItem is properly set to 'x' as expected. When I select 'y', selectedItem in CtrlB $scope gives 'y' as expected.

But when I inspect $scope.selectedItem in CtrlA scope (using AngularJS's batarang), it gives 'x' .

jsFiddle: http://jsfiddle.net/sudhh/GGKjp/2/

Preview page: http://fiddle.jshell.net/sudhh/GGKjp/2/show/light/ (for inspecting with angularjs batarang)

Why is $scope.selectedItem in CtrlA scope not getting updated to 'y'? What is the explanation?

I prefer not to use events or rootScope to update selectedItem in parent scope (for learning purposes).

like image 947
sudhakar Avatar asked Jan 09 '13 09:01

sudhakar


Video Answer


1 Answers

If you try to bind to a primitive declared on parent scope, then the selectedItem in child scope will effectively shadow the property of the same name in the parent scope.

In this case there are 3 choices

  1. define objects in the parent for your model, then reference a property of that object in the child: ref.selectedItem
  2. use $parent.selectedItem (not always possible, but easier than 1. where possible)
  3. define a function on the parent scope, and call it from the child, passing the primitive value up to the parent (not always possible)

More about it on https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance

You can find the updated fiddle using the first approach at http://jsfiddle.net/sudhh/XU2rP/1/

function CtrlA($scope) {
  $scope.items = ['x', 'y'];
  $scope.ref = {
    selectedItem: 'x'
  };
}
like image 56
sudhakar Avatar answered Nov 15 '22 04:11

sudhakar