I am working with a nested array with the structure...
$scope.items = [{attr1: val1,
attr2: val2,
items: [{
attr1: val1,
attr2: val2,
items:
Before rendering data, you can make some preparations. One recursive run over your data to set level value and a link to the parent to each item. Example with your data using LoDash:
var level = 0;
_.each($scope.items, function(item){recursive(item, level)});
function recursive(item, level){
item.level = level;
_.each(item.items, function(innerItem){
innerItem.parent = item;
recursive(innerItem, level+1);
});
}
So now you can easily get parent and siblings of each item.
find an item's parent -> item.parent
find an item's sibling -> item.parent.items[i]
make counts of siblings -> item.parent.items.length
find out how many levels deep an item is nested -> item.level
insert or delete items at any level of the nest (move operation example) ->
newParent.items.push(item);
_.remove(item.parent.items, function(child){return child == item;});
The only minus of this approach which i met - you can not easily clone whole tree without going into endless recursion. But you can make custom cloning function which will not copy links.
If you alias item.items
in the ng-repeat
expression, angular will keep track of the array structure and hierarchical relationships for you.
<div ng-repeat="item in items = item.items">
Then, operations on the tree can simply pass in the item
, the $index
, or the array of items
- without knowledge of the full array structure:
<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>
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);
}
To get the number of siblings, you can refer to items.length
:
<h3>Item #{{$index + 1}} of {{items.length}}</h3>
If you really need to access the parent siblings from child items, you can add another alias for parent = item
and add it to the item using ng-init
:
ng-repeat="item in items = (parent = item).items" ng-init="item.parent = parent"
Then you have access to the grandparent (parent.parent
) and its items
(the parent siblings).
In addition, you can keep track of the current nest level using ng-init
:
ng-init="item.parent = parent; item.level = parent.level + 1"
Here is a working demo: http://plnkr.co/xKSwHAUdXcGZcwHTDmiv