web-dev-qa-db-ja.com

angular 6マテリアルツリーの子ノードから親階層を取得する

tutorial に従ってcdkツリーをangular 6.で実装します。ツリー構造を作成しました。ノードの子を取得するgetDescendantsなどのメソッドがありますが、その逆は利用できません。子またはリーフノードから親階層を取得するにはどうすればよいですか。

5
user9040429

これらのメソッドをツリーコンポーネントに追加しました。フラットツリーを使用していることに注意してください。これはネストされたツリーでは機能しません。

@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を拡張することにより)、そこにこのロジックを移動することを計画しています。

[〜#〜] update [〜#〜]

上記のロジックを自分の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;
      }
    }
  }
}
10
Flauwekeul

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;
          }
      }
  }
}
2
flosej

親階層は、各番号がネストされた再帰ノードのインデックスである番号の配列に格納できます。指定されたノードでツリーを展開するために、以前の例を使用しようとしましたが、最終的にはそのようにすることにしました:

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]);
    });
  }
0
greygreg87