简体   繁体   中英

Angular ng-repeat causes isolated scope

I could use help with understanding how to make these 2 examples work in the same way. For starters, here's my full example: http://jsfiddle.net/tylerbrinks/DZbfD/

I'm using a simple controller to manage index. I realize it's not 100% necessary, but I'm simplifying a much larger problem down to it's most basic parts for help. The controller looks like this:

function TabCtrl($scope){
    $scope.index = 0;
}

I'm using the index value to maintain which item in a list is selected (like tabs).

When elements are already in the DOM, they behave exactly as I'd expect. Clicking each item toggles which item is selected. In the JsFiddle, the color changes to show the selected item.

<div ng-controller="TabCtrl">
    <div ng-class="{selected: index == 0}" ng-click="index = 0">Click Me. Position is 0, scope.index is {{index}}</div>
    <div ng-class="{selected: index == 1}" ng-click="index = 1">Click Me. Position is 1, scope.index is {{index}}</div>
    <div ng-class="{selected: index == 2}" ng-click="index = 2">Click Me. Position is 2, scope.index is {{index}}</div>
</div>

That's perfect - behaves as I'd like. My problem is that I have a dynamic list and I'm using ng-repeat to build it out. When I do, ng-repeat seems to give a new scope to each item in the list. That means I can't toggle between them because they don't share the same index property. Instead, each list item has it's own scope and each scope has a unique index value.

Here's the same thing, but using ng-repeat. Instead of hard coding the index on click, I'm setting it to the $index property of the repeater.

<div ng-controller="TabCtrl">
    <div  ng-repeat="item in [1,2,3]" ng-class="{selected: index == $index}" ng-click="index = $index">Click Me.  Position is: {{$index}}, scope.index is {{index}}</div> 
</div>

How can I make the dynamic list share a single scope like the static list?

Thanks for the help!

You can create an object in your parent scope so that you can use the value in your child scopes. Something like this:

Fiddle

function TabCtrl($scope){
    $scope.myVariables = { index : 0 };
}

<div ng-controller="TabCtrl">
    <div ng-repeat="item in [1,2,3]" ng-class="{selected: myVariables.index == $index}" ng-click="myVariables.index = $index">Click Me.  Position is: {{$index}}, myVariables.index is {{myVariables.index}}</div> 
</div>

Because a new scope is created for each item in the list, your assignment to index will create a new variable in each new scope; essentially, each item in the list has its own copy of the index variable.

Instead, declare your index as a sub-field of the parent scope:

function TabCtrl($scope){
    $scope.container = {
      index: 0
    }
}

And then refer to container.index in your HTML in all the places where you used to refer to index.

I use the rule that all HTML references to scope variables should include the '.' - if they don't then I've probably broken a scoping rule.

Yes you have to have something in your parent scope as others I've said. I personally like to use a function

so in your Controller:

  $scope.activate= function(index){
      $scope.index=index;
  };

and then ng-class:

ng-class="{ active:index=={{$index}}}"

and ng-click:

ng-click="activate({{$index}})"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM