0

I have an item tree in $scope on which I want to iterate with ng-repeat and include a different template according to node type. The tree is something like

$scope.item = {
  ID: 1,
  children: {
    1: {
      ID: 11,
      },
    2: {
      ID: 12,
    }
  },
};

The problem is that when I do something like

<div ng-repeat="item in item.children">
  item.ID : {{item.ID}}
  <div ng-include="showVars(item.ID)"></div>
</div>

the argument of the showVars function is the item.ID value as evaluated in the parent scope, not the subscope created by ng-repeat. When displayed with {{item.ID}}, the value is correct though.

Example in this Fiddle.

My understanding is that the value in the subscope is not updated yet when I call the function, am I right? Is this AngularJS' normal behaviour or a bug?

Edit:

To make it more explicit, in the Fiddle I expect

calling getTemplate with $scope.item.ID = 12 and itemID = 12

instead of

calling getTemplate with $scope.item.ID = 1  and itemID = 12

because ng-repeat is supposed to assign $scope.item with the variable.

Thank you,

Elie Roux
  • 425
  • 1
  • 3
  • 17
  • I don't understand what the problem is. all the logs show that the correct item ID is received by the method: "and itemID = 12". And the included template also displays the child ID: "My Template with item.ID = 12". – JB Nizet Feb 15 '14 at 18:24
  • Sorry, I should have been more explicit : the problem is, as you can see in the log, that, when ng-include is evaluated, $scope.item is still the same as in parent scope, while I would expect it to be the $scope.item of child scope created by ng-repeat. To make it even more explicit, I would expect `calling getTemplate with $scope.item.ID = 12 and itemID = 12` instead of `calling getTemplate with $scope.item.ID = 1 and itemID = 12` – Elie Roux Feb 15 '14 at 18:44

1 Answers1

4

This is expected behavior.

When you created the controller's showVars function, you are closing over $scope, which is the scope of the parent controller. So when you reference $scope, you are getting that scope that was injected into the controller.

In other words, $scope doesn't change based on the execution of the function. This is why you want to pass the item into the function as a parameter.

If you want access to the child scope in the function, you can do this using this:

this.item.ID

Here is a working JS Fiddle

Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • 1
    Thank you very much, this is a great help to me! I globally understand now, especially with the help of [this answer](http://stackoverflow.com/questions/11605917/this-vs-scope-in-angularjs-controllers#answer-14168699) and [this doc](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures). – Elie Roux Feb 15 '14 at 20:54
  • Thanks, @ElieRoux. If you like my answer, please mark it as the correct answer. – Brian Genisio Feb 16 '14 at 02:03