从 Angular 6 材质树中的子节点获取父层次结构

Posted

技术标签:

【中文标题】从 Angular 6 材质树中的子节点获取父层次结构【英文标题】:Get parent hierarchy from a child node in angular 6 material tree 【发布时间】:2018-12-21 19:11:20 【问题描述】:

我正在关注tutorial 以 6 角实现 cdk 树。我创建了一个树结构,现在我想通过使其可点击来从子级获取父层次结构,同时有诸如 getDescendants 之类的方法来获取子级节点,反之亦然不可用。如何从子节点或叶节点获取父层次结构。

【问题讨论】:

【参考方案1】:

我已将这些方法添加到我的树组件中。请注意,我使用的是扁平树,这不适用于嵌套树。

@Component(
  selector: 'es-outline-tree',
  // ...
)
export class OutlineTreeComponent implements OnInit 
  treeControl: FlatTreeControl<FlatTreeNode>;

  // other code...

  /**
   * Recursively expand all parents of the passed node.
   */
  expandParents(node: FlatTreeNode) 
    const parent = this.getParent(node);
    this.treeControl.expand(parent);

    if (parent && parent.level > 0) 
      this.expandParents(parent);
    
  

  /**
   * Iterate over each node in reverse order and return the first node that has a lower level than the passed node.
   */
  getParent(node: FlatTreeNode) 
    const  treeControl  = this;
    const currentLevel = treeControl.getLevel(node);

    if (currentLevel < 1) 
      return null;
    

    const startIndex = treeControl.dataNodes.indexOf(node) - 1;

    for (let i = startIndex; i >= 0; i--) 
      const currentNode = treeControl.dataNodes[i];

      if (treeControl.getLevel(currentNode) < currentLevel) 
        return currentNode;
      
    
  

我打算创建自己的FlatTreeControl(通过扩展 Angular CDK 的FlatTreeControl)并将这个逻辑移到那里。

更新

我已将上述逻辑移至我自己的 FlatTreeControl 实现中:

import  FlatTreeControl  from '@angular/cdk/tree';

export class CustomTreeControl<T> extends FlatTreeControl<T> 
  /**
   * Recursively expand all parents of the passed node.
   */
  expandParents(node: T) 
    const parent = this.getParent(node);
    this.expand(parent);

    if (parent && this.getLevel(parent) > 0) 
      this.expandParents(parent);
    
  

  /**
   * Iterate over each node in reverse order and return the first node that has a lower level than the passed node.
   */
  getParent(node: T) 
    const currentLevel = this.getLevel(node);

    if (currentLevel < 1) 
      return null;
    

    const startIndex = this.dataNodes.indexOf(node) - 1;

    for (let i = startIndex; i >= 0; i--) 
      const currentNode = this.dataNodes[i];

      if (this.getLevel(currentNode) < currentLevel) 
        return currentNode;
      
    
  

【讨论】:

你的帖子让我想到了 BaseTreeControl,它实现了 TreeControl 以找出那里存在的更多权力。 ***.com/questions/52578743/… 这也会触发父节点的兄弟节点 U rock Man...想给100声望 如何在角度8的嵌套树控件中展开特定子节点的所有父节点???我用这段代码修改了一些额外的字段stackblitz.com/angular/…【参考方案2】:

感谢 Flauwekeul,稍微简化了一点

import  FlatTreeControl  from '@angular/cdk/tree';

export class CustomTreeControl<T> extends FlatTreeControl<T> 
  /**
   * Iterate over each node in reverse order and expand each inferior level nodes until level 0.
   */
  expandParents(node: any) 
      const currentLevel = this.getLevel(node);

      if (currentLevel < 1) 
          return null;
      

      const startIndex = this.dataNodes.indexOf(node) - 1;

      for (let i = startIndex; i >= 0; i--) 
          const currentNode = this.dataNodes[i];

          if (this.getLevel(currentNode) < currentLevel) 
              this.expand(currentNode);
              if (this.getLevel(currentNode) === 0) break;
          
      
  

【讨论】:

【参考方案3】:

父层次结构可以存储在数字数组中,其中每个数字是重复嵌套节点的索引。为了在指定节点上展开树,我尝试使用前面的示例,但最终我决定这样做:

1) 每次点击节点都必须调用 ChangePath:

changePath(node) 
if (node.level < this.nodePath.length) 
  this.nodePath.splice(node.level, this.nodePath.length - node.level);

this.nodePath.push(this.treeControl.dataNodes.indexOf(node));

2)接下来,当树崩溃时,我们必须调用nodePath中每个项目的展开(当树崩溃是由于删除节点我们不想展开它时,所以从路径中删除最后一个元素):

expandTreeOnSpecifiedNode(isDelete: boolean) 
  if (isDelete) 
    this.nodePath.pop();
  
  this.nodePath.forEach(id => 
    console.log(id);
    this.treeControl.expand(this.treeControl.dataNodes[id]);
    );
  

【讨论】:

层次结构可以很容易地用 this.nodePath.push(this.node) 谢谢人!很棒

以上是关于从 Angular 6 材质树中的子节点获取父层次结构的主要内容,如果未能解决你的问题,请参考以下文章

Angular Material - 扁平树和嵌套树之间的区别

疯狂Java——树和二叉树(第11章)

从Angular 5中的子组件更新父布尔值

从Angular 2中的子组件更新父组件属性

JZ8 二叉树的下一个结点

在完美二叉树中获取顶点的父节点