将变量注入 ngRepeat

Inject variables into ngRepeat

我有一个递归的 ng-repeat 用于创建一个分支思维导图树,它可能有无限的子节点(运行 下面的代码片段可以更好地理解我的意思)。

我的 $scope 中有一个 remove() 函数,它打算自行删除。但是,为此,我需要访问父级。我尝试通过使用 ng-init 在名为 parent 的变量中设置父节点来实现这一点。问题是, parent 变量似乎指的是节点本身而不是其父节点。我该如何将父级注入循环?

除上述 $scope.remove() 之外的所有内容都适用于以下代码段:

(function(){
 angular
 .module('createTree',[])
 .controller('CreateTreeController', function($scope){
  $scope.tree=[{
   title:'node 1',
   subNodes:[
    {
     title:'node 1.1',
     subNodes:[]
    },
    {
     title:'node 1.2',
     subNodes:[
      {
       title:'node 1.2.1',
       subNodes:[]
      },
      {
       title:'node 1.2.2',
       subNodes:[]
      }
     ]
    },
    {
     title:'node 1.3',
     subNodes:[]
    }
   ]
  }];
  $scope.addTo=function(node){
   node.subNodes.push({
    title: node.title+"."+(node.subNodes.length+1),
    subNodes:[]
   });
  }
  $scope.remove=function(node,parent){
   var index=parent.subNodes.indexOf(node)
   if(index>-1) parent.subNodes.splice(index,1);
  }
 });
})();
*{
 position: relative;
 box-sizing: border-box;
}

.node{
 padding: 1px 0;
}

.node>.subNodes{
 margin-left: 10px;
}

.node>.subNodes::before{
 content: '';
 display: block;
 width: 5px;
 height: 1px;
 background-color: black;
 position: absolute;
 top: 50%;
 left: -10px;
}
.node>.subNodes::after{
 content:'';
 display: block;
 width: 1px;
 height: 100%;
 background-color: black;
 position: absolute;
 top: 0;
 left: -5px;
 z-index: 1;
}
.node>.subNodes>.node::before{
 content:'';
 display: block;
 width: 5px;
 height: 1px;
 background-color: black;
 position: absolute;
 top: 50%;
 left:-5px;
 z-index: 3;
}

.node>.subNodes>.node:first-child::after{
 content:'';
 display: block;
 width: 1px;
 height: 50%;
 background-color: white;
 position: absolute;
 top: 0;
 left:-5px;
 z-index: 2;
}
.node>.subNodes>.node:last-child:not(:first-child)::after{
 content:'';
 display: block;
 width: 1px;
 height: calc(50% - 1px);
 background-color: white;
 position: absolute;
 bottom: 0;
 left:-5px;
 z-index: 2;
}

.node>.subNodes>.node:only-child::after{
 height: 100%;
}


.node>*{
 display: inline-block;
 vertical-align: middle;
}

.node [type=text]{
 width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
 
<div ng-app="createTree" ng-controller="CreateTreeController as createTree">
 
 <script type="text/ng-template" id="treeNode.html">
  <span>
   <input
    type="button"
    value="x"
    ng-click="remove(node,parent)"
   >
   <a href="#">{{node.title}}</a>, parent: {{parent.title}}
   <input 
    type="button" 
    value="+" 
    ng-click="addTo(node)"
   >
  </span><div class="subNodes" ng-show="node.subNodes.length>0">
   <div 
    class="node" 
    ng-init="parent=node"
    ng-repeat="node in node.subNodes" 
    ng-include="'treeNode.html'"
   ></div>
  </div>
 </script>

 <div 
  class="node"
  ng-init="parent=tree"
  ng-repeat="node in tree" 
  ng-include="'treeNode.html'"
 ></div>

</div>

您在每个循环中更新 parent 的方式存在问题。基本上发生的事情是,在第一级之后,您 parent 的值变得与节点相同。这实际上是一个 angular 特性,其中 ng-init 被再次调用以更新 parent 的值,因为它看到节点的值在 ng-repeat 中发生了变化。所以最终结果是 parent 的值永远是 node.subNodes 中的最后一个元素。因此,当您调用 remove 时,节点的 parent 并没有真正被传递。为了克服这个问题,我添加了第三个变量,它将保存 parent(或者更确切地说是下一个 parent)的值。我创建了一个提琴手 here.
我只更改了您的 HTML 如下(ng-init 表达式已更改):

<div ng-controller="CreateTreeController">
  <script type="text/ng-template" id="treeNode.html">
    <span>
            <input
                type="button"
                value="x"
                ng-click="remove(node,parent)"
            >
            <a href="#">{{node.title}}</a>, parent: {{parent.title}}
            <input 
                type="button" 
                value="+" 
                ng-click="addTo(node)"
            >
        </span>
    <div class="subNodes" ng-show="node.subNodes.length>0">
      <div class="node" ng-init="parent=oldParent;oldParent=node;" ng-repeat="node in node.subNodes" ng-include="'treeNode.html'"></div>
    </div>
  </script>

  <div class="node" ng-init="parent=tree;oldParent=parent[0];" ng-repeat="node in tree" ng-include="'treeNode.html'"></div>
</div>

父节点不能是节点,需要为每个节点设置真正的父节点。

我做了一个解决方案

(function(){
 angular
 .module('createTree',[])
 .controller('CreateTreeController', function($scope){
  $scope.tree=[{
   title:'node 1',
            parent: null,
   subNodes:[]
  }];
  $scope.addTo=function(node){
   node.subNodes.push({
    title: node.title+"."+(node.subNodes.length+1),
                parent: node,
    subNodes:[]
   });
  }
  $scope.remove=function(node,parent){
   var index=node.parent.subNodes.indexOf(node)
   if(index>-1 && node.parent != null) node.parent.subNodes.splice(index,1);
  }
 });
})();
*{
 position: relative;
 box-sizing: border-box;
}

.node{
 padding: 1px 0;
}

.node>.subNodes{
 margin-left: 10px;
}

.node>.subNodes::before{
 content: '';
 display: block;
 width: 5px;
 height: 1px;
 background-color: black;
 position: absolute;
 top: 50%;
 left: -10px;
}
.node>.subNodes::after{
 content:'';
 display: block;
 width: 1px;
 height: 100%;
 background-color: black;
 position: absolute;
 top: 0;
 left: -5px;
 z-index: 1;
}
.node>.subNodes>.node::before{
 content:'';
 display: block;
 width: 5px;
 height: 1px;
 background-color: black;
 position: absolute;
 top: 50%;
 left:-5px;
 z-index: 3;
}

.node>.subNodes>.node:first-child::after{
 content:'';
 display: block;
 width: 1px;
 height: 50%;
 background-color: white;
 position: absolute;
 top: 0;
 left:-5px;
 z-index: 2;
}
.node>.subNodes>.node:last-child:not(:first-child)::after{
 content:'';
 display: block;
 width: 1px;
 height: calc(50% - 1px);
 background-color: white;
 position: absolute;
 bottom: 0;
 left:-5px;
 z-index: 2;
}

.node>.subNodes>.node:only-child::after{
 height: 100%;
}


.node>*{
 display: inline-block;
 vertical-align: middle;
}

.node [type=text]{
 width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
 
<div ng-app="createTree" ng-controller="CreateTreeController as createTree">
 
 <script type="text/ng-template" id="treeNode.html">
  <span>
   <input
    type="button"
    value="x"
    ng-click="remove(node)"
   >
   <a href="#">{{node.title}}</a>, parent: {{node.parent.title}}
   <input 
    type="button" 
    value="+" 
    ng-click="addTo(node)"
   >
  </span><div class="subNodes" ng-show="node.subNodes.length>0">
   <div 
    class="node"
    ng-repeat="node in node.subNodes" 
    ng-include="'treeNode.html'"
   ></div>
  </div>
 </script>

 <div 
  class="node"
  ng-repeat="node in tree" 
  ng-include="'treeNode.html'"
 ></div>

</div>