web-dev-qa-db-fra.com

Obtenir la hiérarchie parent à partir d'un nœud enfant dans angular 6 arbre de matériaux

Je suis un tutoriel pour implémenter l'arborescence cdk dans angular 6. J'ai créé une structure arborescente, maintenant je veux obtenir la hiérarchie parent de l'enfant en la faisant cliquable, alors qu'il existe des méthodes comme getDescendants pour obtenir les enfants d'un nœud, l'inverse n'est pas disponible. Comment puis-je obtenir la hiérarchie parent d'un nœud enfant ou feuille.

5
user9040429

J'ai ajouté ces méthodes à mon composant d'arborescence. Notez que j'utilise l'arbre plat, cela ne fonctionnera pas pour un arbre imbriqué.

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

Je prévois de créer mon propre FlatTreeControl (en étendant Angular CDK's FlatTreeControl) et déplacer cette logique là.

MISE À JOUR

J'ai déplacé la logique ci-dessus vers ma propre implémentation 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

Merci à Flauwekeul, un peu simplifié

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

La hiérarchie parent peut être stockée dans un tableau de nombres où chaque nombre est l'index du nœud imbriqué récurrent. Afin d'étendre l'arborescence sur le nœud spécifié, j'ai essayé d'utiliser les exemples précédents, mais j'ai finalement décidé de le faire de cette façon:

1) ChangePath doit être appelé chaque fois que nous cliquons sur le nœud:

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) Ensuite, lorsque l'arbre s'effondre, nous devons appeler l'expansion de chaque élément dans nodePath (lorsque l'effondrement de l'arbre est causé par la suppression du nœud, nous ne voulons pas le développer, donc le dernier élément est supprimé du chemin):

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