在嵌套的 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 值的主要内容,如果未能解决你的问题,请参考以下文章
如何在AngularJS中使用ng-repeat创建嵌套结构[关闭]
如何在angularjs中使用带有嵌套ng-repeat的复选框