pos*_*est 5 angularjs angularjs-ng-repeat
我正在使用具有结构的嵌套数组...
$scope.items = [{attr1: val1,
attr2: val2,
items: [{
attr1: val1,
attr2: val2,
items: [{
...
}, ...]
}, ...]
}, ...];
Run Code Online (Sandbox Code Playgroud)
它进入一个ng-repeat与ng-include像这样
<div ng-repeat="item in items" ng-include="'/path/to/template.tpl.html'"></div>
Run Code Online (Sandbox Code Playgroud)
并且template.tpl.html是
<div>{{item.attr1}}<\div>
<div>{{item.attr2}}<\div>
<div ng-click="fnAddNewItemBelow(item, $parent)"><\div>
<div ng-repeat="item in item.items" ng-include="'/path/to/template.tpl.html'"><\div>
Run Code Online (Sandbox Code Playgroud)
现在,在控制器中,我通常想要做的事情
但我不确定如何优雅地做到这一点.我想想要实现fnAddNewItemBelow.我能解决的两个选择是
使用Angular提供的嵌套范围结构
// pseudo-code only
$scope.fnAddNewItemBelow = function (item, parent) {
var newItem = ...;
// add newItem as a sibling after the item that was ng-clicked
// parent.$parent is necessary because the ng-include adds another scope layer (I think)
parent.$parent.item.items.push(newItem);
// (probably need to use .splice in case there are items after item,
// but I'm keeping it simple)
}
Run Code Online (Sandbox Code Playgroud)
但这很丑陋,因为它假设了太多的结构(如果我把一个ng-if放到它上面<div ng-click...,这会增加另一个范围级别...然后我需要parent.$parent.$parent.item.items.push(newItem)).
另一种方法是直接操作$scope.items,因为Angular将更新与其关联的UI和范围.我可以通过$scope.items使用for循环递归迭代,并在通过它具有的一些唯一ID定位项之后,在它之后插入newItem
// pseudo-code only
$scope.fnAddNewItemBelow = function (item) {
var newItem = ...;
// add newItem as a sibling after the item that was ng-clicked
fnSomeFunctionToFindItemAndInsertItemAfterIt(item.id, newItem);
}
fnSomeFunctionToFindItemAndInsertItemAfterIt (itemId, newItem) {
// fancy recursive function that for loops through each item, and calls
// itself when there are children items. When it finds item with itemId, it
// splices in the newItem after
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢这个,因为每次我想对嵌套数组做一些事情时,它都需要遍历整个项目树.
有更优雅的解决方案吗?
如果item.items在ng-repeat表达式中使用别名,angular将跟踪数组结构和层次关系.
<div ng-repeat="item in items = item.items">
Run Code Online (Sandbox Code Playgroud)
然后,在树操作可以简单地通过在item的$index,或数组items-不完整的阵列结构的知识:
<button ng-click="addItem(item)">Add to my items</button>
<button ng-click="addSiblingItem(items, $index)">Add a sibling item</button>
<button ng-click="deleteMe(items, $index)">Delete Me</button>
Run Code Online (Sandbox Code Playgroud)
JS:
$scope.addItem = function(item) {
item.items.push({
attr1: 'my new - attr1',
attr2: 'my new - attr2',
items: []
});
}
$scope.addSiblingItem = function(items, position) {
items.splice(position + 1, 0, {
attr1: 'sibling - new attr1',
attr2: 'sibling - new attr2',
items: []
});
}
$scope.deleteMe = function(items, position) {
items.splice(position, 1);
}
Run Code Online (Sandbox Code Playgroud)
要获得兄弟姐妹的数量,您可以参考items.length:
<h3>Item #{{$index + 1}} of {{items.length}}</h3>
Run Code Online (Sandbox Code Playgroud)
如果您确实需要从子项访问父级兄弟,则可以添加另一个别名parent = item并使用ng-init以下内容将其添加到项:
ng-repeat="item in items = (parent = item).items" ng-init="item.parent = parent"
Run Code Online (Sandbox Code Playgroud)
然后您可以访问grandparent(parent.parent)及其items(父级兄弟姐妹).
此外,您可以使用ng-init以下方法跟踪当前嵌套级别:
ng-init="item.parent = parent; item.level = parent.level + 1"
Run Code Online (Sandbox Code Playgroud)
这是一个工作演示:http://plnkr.co/xKSwHAUdXcGZcwHTDmiv