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

Posted

技术标签:

【中文标题】在嵌套的 ng-repeat 中传递 2 个 $index 值【英文标题】:passing 2 $index values within nested ng-repeat 【发布时间】:2013-02-21 18:57:48 【问题描述】:

所以我有一个 ng-repeat 嵌套在另一个 ng-repeat 中,以构建导航菜单。在内部 ng-repeat 循环上的每个 <li> 上,我设置了一个 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>

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

【问题讨论】:

为什么要传递$index?只需像这样ng-click="loadFromMenu(section)" 传递对象引用。传递 $index 意味着您将执行一个循环来查找不必要的对象。 【参考方案1】:

每个 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 值。我试着把它们放在一个数组中,它起作用了:) 你不必使用数组:ng-click="loadFromMenu($parent.$index, $index)" 你甚至不需要传入索引——在 loadFromMenu 中,它应该可以访问 this 对象,这将使你可以访问:this.$index 和 this.$parent。 $索引 @Oddman 尽管这是可能的,但我认为这不是一个好主意,因为您将 loadFromMenu 硬连线以在具有 $index 和父级范围的对象的上下文中运行范围与 $index。假设您然后例如在菜单中创建组,在两个重要的之间生成另一​​个范围 - 您将不得不更改 loadFromMenu 而不是更改对它的调用。如果在某些菜单中您需要调用loadFromMenu($parent.$parent.$index,$index),而在某些菜单中您只需要loadFromMenu($parent.$index,$index),那么使用this.... 将无法正常工作。 你不应该使用 $parent.$index 因为它不是很安全。如果你在循环中添加一个 ng-if,你会弄乱 $index,检查:plnkr.co/52oIhLfeXXI9ZAynTuAJ【参考方案2】:

$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

【讨论】:

这是实现此效果的推荐方法。事实上,Angular 团队已经多次表示这是 ng-init 指令的少数推荐用途之一(参见:link)。我经常发现使用 $parent (根据当前接受的答案)有点代码味道,因为通常有更好的方法来实现 $scope 到 $scope 的通信(服务或广播/发射事件)并将其分配给命名变量,它的值代表什么变得更清楚。 IMO 这个答案比接受的要好得多。使用 $parent 真的非常不建议。 当您从列表中删除项目时,这将停止工作,因为 ng-init 值不会重新初始化。仅当您不打算从列表中删除项目时它才有用。 看起来角语法进化了。 ***.com/a/31477492/2516560 您现在可以在数据中使用“ng-repeat = (key,value)” 过去我写了这个答案,这是 Angular 1.X 的方法。 ng-init 的这种用法在 ng-init 文档中得到了演示,在 ng-repeat 文档中没有单独提及,所以我在这里写了 + 修改了 Github 上的文档。当前的ng-repeat 语法有更好的方法来实现这一点,@Okazari 证明了这一点。它没有您在 cmets 中提到的一些缺陷。【参考方案3】:

如何使用这种语法(看看这个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 并区分这两个索引。

【讨论】:

当你有多个嵌套循环时,我认为这比使用 parent 更干净 实际上,在使用 angular-ui-tree 拖放节点时,这给我带来了一些实际问题。索引似乎没有重置,结果发生了奇怪的事情。 @MikeTaverne 你能尝试在 plunker 中复制吗?我很想看看这种行为。 这是完成此任务并避免任何潜在问题的正确方法。 ng-init 适用于初始渲染,但如果在页面上更新对象,它会中断。 好!但请像 plunker 示例一样添加“track by”来修复。【参考方案4】:

只是为了帮助到达这里的人......你不应该使用 $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.angularjs.org/api/ng/directive/ngRepeat)。这里的重点是“ng-init”——这是角度文档同意的正确方式。 @gonzalon 如何在 ng click 中将这些索引作为参数传递 我正在做 removeList($index) 或 removeList(rowIndex) 它没有在函数中正确记录索引我收到的索引值为 undefined 。我正在使用角度 1.5.6 这是正确的方法,你不应该访问 $parent【参考方案5】:

只需使用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>

【讨论】:

【参考方案6】:

当您处理对象时,您希望尽可能方便地忽略简单的 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。

【讨论】:

以上是关于在嵌套的 ng-repeat 中传递 2 个 $index 值的主要内容,如果未能解决你的问题,请参考以下文章

ng-repeat 嵌套 ng-switch 出错解决

如何在AngularJS中使用ng-repeat创建嵌套结构[关闭]

如何在angularjs中使用带有嵌套ng-repeat的复选框

如何使用 ng-repeat 调用返回对象的函数

为啥 ng-click 需要通过 $index 跟踪才能在嵌套的 ng-repeat 内触发

ng-repeat动态创建嵌套ng-repeats的数组