在嵌套的ng-repeat中传递2个$ index值


322

因此,我在另一个ng-repeat中嵌套了一个ng-repeat,以构建导航菜单。在<li>内部ng-repeat循环的每个循环上,我都设置了一个ng-click,它通过传入$ index来调用该菜单项的相关控制器,以使应用知道我们需要哪个。但是,我还需要从外部ng-repeat中传递$ index,以便应用程序知道我们在哪个部分以及哪个教程中。

<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>

这是一个傻瓜http://plnkr.co/edit/bJUhI9oGEQIql9tahIJN?p=preview


为什么要通过$ index?只需像这样传递对象引用ng-click="loadFromMenu(section)"。传递$ index意味着您将循环查找不需要的对象。
Moshii's

Answers:


468

每个ng-repeat都会使用传递的数据创建一个子作用域,并$index在该作用域中添加一个附加变量。

因此,您需要做的是达到父级作用域,然后使用该范围$index

看到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>

太棒了,所以这就是我访问外部$ index的方式,但是我需要同时传入$ index值。我尝试将它们放在一个数组中,并且起作用了:)
Tules

16
您不必使用数组: ng-click="loadFromMenu($parent.$index, $index)"
Mark Rajcok

3
您甚至不必传递索引-在loadFromMenu中,它应该可以访问this对象,这将使您可以访问:this。$ index和this。$ parent。$ index
Oddman

3
@Oddman即使这是可能的,我也不认为这是一个好主意,因为您然后硬连接loadFromMenu使其在具有$ index作用域和$ index父作用域的对象的上下文中运行。假设您然后例如在菜单中创建了两个在两个重要范围之间生成另一​​个范围的组-您将必须更改loadFromMenu而不是更改对其的调用。而且,如果在某些菜单中需要调用loadFromMenu($parent.$parent.$index,$index),而在某些菜单中则需要loadFromMenu($parent.$index,$index)使用,则使用this....将不起作用。
epeleg 2014年

7
您不应该使用$ parent。$ index,因为它并不安全。如果在循环中添加ng-if,则会使$ index混乱,请检查:plnkr.co/52oIhLfeXXI9ZAynTuAJ
gonzalon 2014年

201

$parent.$index使用方法更优雅的解决方案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


2
这是实现此效果的推荐方法。实际上,角度小组曾几次表示这是ng-init指令的少数推荐用法之一(请参阅:link)。我经常发现使用$ parent(根据当前接受的答案)有点代码味道,因为通常存在更好的方法来实现$ scope到$ scope的通信(服务或广播/发射事件)并将其分配给命名变量可以更清楚地表示值的含义。
大卫·比奇

2
IMO这个答案比公认的要好得多。确实不建议使用$ parent。
olivarra1 2014年

43
当您从列表中删除项目时,这会停止工作,因为ng-init值不会重新初始化。仅当您不打算从列表中删除项目时,它才有用。
Jesse Greathouse 2014年

6
看起来像角度语法进化了。stackoverflow.com/a/31477492/2516560,您现在可以使用“ ng-repeat =(数据中的(键,值)”)
Okazari 2015年

2
那时我写了这个答案,这就是针对Angular 1.X的方法。的这种用法ng-init已在ng-init文档中得到了证明,而在文档中没有任何提及ng-repeat,因此我在此处撰写并修改了Github上的文档。ng-repeat@Okazari演示了当前语法有更好的方法来实现此目的。它没有您在评论中提到的一些缺陷。
vucalur

115

如何使用这种语法(请看一下这个plunker)。我刚刚发现了它,而且非常棒。

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

例:

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

使用这种语法,您可以给自己命名,$index并区分两个索引。


8
我认为当您有多个嵌套循环时,这比使用父级要干净得多
Yasitha Chinthaka 2015年

实际上,这在使用angular-ui-tree拖放节点时给我带来了一些实际问题。索引似乎没有重置,结果发生了奇怪的事情。
Mike Taverne 2015年

@MikeTaverne您可以尝试在一个塞子中重现吗?我希望看到这种行为。
Okazari 2015年

4
这是完成此任务并避免任何潜在问题的正确方法。ng-init适用于初始渲染,但是如果对象在页面上更新,则会中断。
埃里克·马丁

好!但请像插入代码示例一样修正添加“ track by”的问题。
达尼洛

32

只是为了帮助到达这里的人...您不应该使用$ parent。$ index,因为它并不真正安全。如果在循环中添加ng-if,则会使$ index混乱!

正确的方法

  <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>

检查:plnkr.co/52oIhLfeXXI9ZAynTuAJ


请注意,这里不需要“ track by”-这是用于ng-repeat的另一件事,用于了解唯一项并监视集合中的更改(请参见docs.docs.angularjs.org的 “ Tracking and Duplicates”部分/ api / ng / directive / ngRepeat)。此处的重点是“ ng-init”-这是与角度文档一致的正确方法。
丽贝卡

@gonzalon如何在ng click
中将

我正在做removeList($ index)或removeList(rowIndex)它没有在我收到未定义的索引值的函数中正确记录索引。我使用的是角度1.5.6
user269867

这是正确的方式,你永远不应该访问$父
JESU卡斯蒂略

3

在处理对象时,您希望尽可能方便地忽略简单id。

如果您将点击线更改为此,我认为您会顺利进行的:

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

另外,我认为您可能需要更改

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

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

请参阅http://docs.angularjs.org/misc/faq并查找ng-class。


1

只需使用 ng-repeat="(sectionIndex, section) in sections"

并且可以在下一级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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.