AngularJS: moving nested arrays

I work with a nested array with structure ...

$scope.items = [{attr1: val1, 
  attr2: val2,
  items: [{
     attr1: val1, 
     attr2: val2,
     items: [{
     ... 
     }, ...]
  }, ...]
}, ...];

which goes into ng-repeatwith ng-includelike that

<div ng-repeat="item in items" ng-include="'/path/to/template.tpl.html'"></div>

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

Now, in the controller, I usually want to do something like

  • find parent element
  • find sibling element
  • do siblings counts
  • Find out how many levels are nested in an element.
  • insert or remove items at any level of the socket

But I'm not sure how to do it elegantly. For example, imagine what I wanted to implement fnAddNewItemBelow. Two options are possible:

Areas of movement

Use the nested area structure in which Angular provides

// 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)
}

, (, ng-if <div ng-click..., ... parent.$parent.$parent.item.items.push(newItem)).

, item.id

$scope.items, Angular , . $scope.items, , , , 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
}

, , - .

?

+4
2

item.items ng-repeat, angular .

<div ng-repeat="item in items = item.items">

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>

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);
}

, items.length:

<h3>Item #{{$index + 1}} of {{items.length}}</h3>

, parent = item ng-init:

ng-repeat="item in items = (parent = item).items" ng-init="item.parent = parent"

(parent.parent) items (-).

, ng-init:

ng-init="item.parent = parent; item.level = parent.level + 1"

: http://plnkr.co/xKSwHAUdXcGZcwHTDmiv

+6

. , . 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);
    });
}

, .

item.parent

sibling → item.parent.items[i]

item.parent.items.length

, → item.level

( ) →

newParent.items.push(item);
_.remove(item.parent.items, function(child){return child == item;});

, - , . , .

+1

Source: https://habr.com/ru/post/1538220/


All Articles