220

I want to use the index of the parent list (foos) as an argument to a function call in the child list (foos.bars).

I found a post where someone recommends using $parent.$index, but $index is not a property of $parent.

How can I access the index of the parent ng-repeat?

<div ng-repeat="f in foos">
  <div>
    <div ng-repeat="b in foos.bars">
      <a ng-click="addSomething($parent.$index)">Add Something</a>
    </div>
  </div>
</div>
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Coder1
  • 13,139
  • 15
  • 59
  • 89
  • 2
    It seems to work correctly for me. I've wrote a plunker to show it working: http://plnkr.co/edit/BenCDh4NUGPPHKWGsGMr?p=preview Can you provide more detail? – Piran Feb 11 '13 at 07:08
  • Thank you for that. It led me to find my issue was a bug in my markup. – Coder1 Feb 11 '13 at 07:20
  • @Coder1, please consider deleting this question. – Mark Rajcok Feb 11 '13 at 22:18
  • 7
    @MarkRajcok I did consider it last night, but thought it would be helpful to others searching for how to do this, so I left it. – Coder1 Feb 11 '13 at 22:41
  • 2
    Well, if you want to keep it, please add an answer and accept it (so this question doesn't remain on the "unanswered" list). – Mark Rajcok Feb 11 '13 at 22:47

6 Answers6

284

My example code was correct and the issue was something else in my actual code. Still, I know it was difficult to find examples of this so I'm answering it in case someone else is looking.

<div ng-repeat="f in foos">
  <div>
    <div ng-repeat="b in foos.bars">
      <a ng-click="addSomething($parent.$index)">Add Something</a>
    </div>
  </div>
</div>
Coder1
  • 13,139
  • 15
  • 59
  • 89
  • 13
    Also- this threw me for a while. If there is an data-ng-switch directive within your code, you'll need to go up an additional scope level- ($parent.$parent.$index). Not pretty, I know. – Hairgami_Master Mar 28 '13 at 13:18
  • Agreed. I needed to pass $parent.$parent.$index to my controller function to get the correct value but then bind my ng-show to $parent.$index. Seems like an angular bug to me – Andrew Gray Feb 16 '15 at 06:19
  • Can I do something like this if I have one Collection repeat along with ng-repeat?Apparently it is returning undefined doing the same – Ali Sadiq Oct 05 '16 at 06:15
  • 7
    Just to add - you need an additional $parent even if you have an `ng-if` in the code as I just found out. – Plasty Grove Oct 26 '16 at 01:42
  • @PlastyGrove Thank you for pointing out that ``ng-if`` requires and additional ``$parent`` reference. Saved me some headache. – iiminov Jul 06 '17 at 08:35
220

According to ng-repeat docs http://docs.angularjs.org/api/ng.directive:ngRepeat, you can store the key or array index in the variable of your choice. (indexVar, valueVar) in values

so you can write

<div ng-repeat="(fIndex, f) in foos">
  <div>
    <div ng-repeat="b in foos.bars">
      <a ng-click="addSomething(fIndex)">Add Something</a>
    </div>
  </div>
</div>

One level up is still quite clean with $parent.$index but several parents up, things can get messy.

Note: $index will continue to be defined at each scope, it is not replaced by fIndex.

Samuel Jaeschke
  • 1,126
  • 11
  • 23
Samuli Ulmanen
  • 2,841
  • 1
  • 16
  • 10
  • I don't understand the Note. Isn't the whole point of this question because that isn't true? – adam-beck Nov 18 '14 at 20:45
  • 16
    This should be the validated answer as it's cleaner than the `$parent.$index` one – tdebroc May 07 '15 at 15:26
  • 1
    @adam-beck I think they mean that when using this `(fIndex, f)` method, $index will still be defined (not omitted) - so the index becomes accessible as both `$index` and `fIndex`. – Samuel Jaeschke Sep 04 '15 at 07:10
  • 1
    For my case, using `$index` does not work, but adding the `fIndex` does. I have not a single clue as to *why* `$index` does not work (it does in other places in my code), but after struggling for several days I stopped caring when I found this answer. It is also a bit more readable when you have multiple `ng-repeat`s IMO. – Krøllebølle Jan 19 '16 at 10:00
  • @Krøllebølle the reason it works the way you see it is that each `ng-repeat` iteration creates its own scope, which also defines its own `$index`, overwriting the parent's `$index`. If you include a `{{$index}}` right above or below the innermost `ng-repeat`-ed element, you'll see the parent's value, and putting it inside the innermost `ng-repeat`-ed element will show you the child's. Using the approach in this answer just assigns the parent index to a variable whose name you've chosen (`fIndex`) so it won't get overwritten by a child scope. – tavnab Feb 18 '16 at 14:00
  • The variable doesn't get updated if you delete an element which was in the repeat array. $index and $parent.$index is always the safe choice – Bharath Bhandarkar May 04 '16 at 17:06
46

Take a look at my answer to a similar question.
By aliasing $index we do not have to write crazy stuff like $parent.$parent.$index.


Way more elegant solution whan $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

Community
  • 1
  • 1
vucalur
  • 6,007
  • 3
  • 29
  • 46
12

You can also get control of grand parent index by the following code

$parent.$parent.$index
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
AkRoy
  • 343
  • 4
  • 10
2

You can simply use use $parent.$index .where parent will represent object of parent repeating object .

Vivek Panday
  • 1,426
  • 2
  • 16
  • 34
0

$parent doesn't work if there are multiple parents. instead of that we can define a parent index variable in init and use it

<div data-ng-init="parentIndex = $index" ng-repeat="f in foos">
  <div>
    <div data-ng-init="childIndex = $index" ng-repeat="b in foos.bars">
      <a ng-click="addSomething(parentIndex)">Add Something</a>
    </div>
  </div>
</div>
  • see answer from vucalur here it also mentions this. In general this is the correct way to go IMO and generally only proper use for ng-init. Any time people are reaching up to $parent you are asking for trouble when the context of your code changes. – shaunhusain Nov 29 '17 at 09:55