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

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

【问题讨论】:

    标签: angular typescript angular-material angular6 angular-cdk


    【解决方案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 以找出那里存在的更多权力。
    • 这也会触发父节点的兄弟节点
    • 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) 谢谢人!很棒
      猜你喜欢
      • 1970-01-01
      • 2020-05-29
      • 2011-10-29
      • 2012-03-11
      • 1970-01-01
      • 2019-01-07
      • 2019-08-30
      • 1970-01-01
      • 2019-09-18
      相关资源
      最近更新 更多