passing 2 $index values within nested ng-repeat

AngularjsAngularjs Ng-Repeat

Angularjs Problem Overview


So I have an ng-repeat nested within another ng-repeat in order to build a nav menu. On each <li> on the inner ng-repeat loop I set an ng-click which calls the relevant controller for that menu item by passing in the $index to let the app know which one we need. However I need to also pass in the $index from the outer ng-repeat so the app knows which section we are in as well as which tutorial.

<ul ng-repeat="section in sections">
	<li  class="section_title {{section.active}}" >
		{{section.name}}
	</li>
	<ul>
		<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu($index)" ng-repeat="tutorial in section.tutorials">
			{{tutorial.name}}
		</li>
	</ul>
</ul>

here's a Plunker http://plnkr.co/edit/bJUhI9oGEQIql9tahIJN?p=preview

Angularjs Solutions


Solution 1 - Angularjs

Each ng-repeat creates a child scope with the passed data, and also adds an additional $index variable in that scope.

So what you need to do is reach up to the parent scope, and use that $index.

See http://plnkr.co/edit/FvVhirpoOF8TYnIVygE6?p=preview

<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu($parent.$index)" ng-repeat="tutorial in section.tutorials">
    {{tutorial.name}}
</li>

Solution 2 - Angularjs

Way more elegant solution than $parent.$index is using ng-init:

<ul ng-repeat="section in sections" ng-init="sectionIndex = $index">
    <li  class="section_title {{section.active}}" >
        {{section.name}}
    </li>
    <ul>
        <li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu(sectionIndex)" ng-repeat="tutorial in section.tutorials">
            {{tutorial.name}}
        </li>
    </ul>
</ul>

Plunker: http://plnkr.co/edit/knwGEnOsAWLhLieKVItS?p=info

Solution 3 - Angularjs

What about using this syntax (take a look in this plunker). I just discovered this and it's pretty awesome.

ng-repeat="(key,value) in data"

Example:

<div ng-repeat="(indexX,object) in data">
    <div ng-repeat="(indexY,value) in object">
       {{indexX}} - {{indexY}} - {{value}}
    </div>
</div>

With this syntax you can give your own name to $index and differentiate the two indexes.

Solution 4 - Angularjs

Just to help someone who get here... You should not use $parent.$index as it's not really safe. If you add an ng-if inside the loop, you get the $index messed!

Right way

  <table>
    <tr ng-repeat="row in rows track by $index" ng-init="rowIndex = $index">
  		<td ng-repeat="column in columns track by $index" ng-init="columnIndex = $index">
  		  
  		  <b ng-if="rowIndex == columnIndex">[{{rowIndex}} - {{columnIndex}}]</b>
  		  <small ng-if="rowIndex != columnIndex">[{{rowIndex}} - {{columnIndex}}]</small>
  		  
  		</td>
  	</tr>
  </table>

Check: plnkr.co/52oIhLfeXXI9ZAynTuAJ

Solution 5 - Angularjs

Just use ng-repeat="(sectionIndex, section) in sections"

and that will be useable on the next level ng-repeat down.

<ul ng-repeat="(sectionIndex, section) in sections">
    <li  class="section_title {{section.active}}" >
        {{section.name}}
    </li>
    <ul>
        <li ng-repeat="tutorial in section.tutorials">
            {{tutorial.name}}, Your section index is {{sectionIndex}}
        </li>
    </ul>
</ul>

Solution 6 - Angularjs

When you are dealing with objects, you want to ignore simple id's as much as convenient.

If you change the click line to this, I think you will be well on your way:

<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu(tutorial)" ng-repeat="tutorial in section.tutorials">

Also, I think you may need to change

class="tutorial_title {{tutorial.active}}"

to something like

ng-class="tutorial_title {{tutorial.active}}"

See http://docs.angularjs.org/misc/faq and look for ng-class.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTulesView Question on Stackoverflow
Solution 1 - AngularjsAlex OsbornView Answer on Stackoverflow
Solution 2 - AngularjsvucalurView Answer on Stackoverflow
Solution 3 - AngularjsOkazariView Answer on Stackoverflow
Solution 4 - AngularjsGonzView Answer on Stackoverflow
Solution 5 - AngularjsRobKohrView Answer on Stackoverflow
Solution 6 - AngularjskwerleView Answer on Stackoverflow