I am following a tutorial to implement cdk tree in angular 6. I created a tree structure, now I want to get the parent hierarchy from from the child by making it clickable, while there are methods like getDescendants to get children of a node, vice versa is not available. How can I get the parent hierarchy from a child or leaf node.
I've added these methods to my tree component. Note that I use the flat tree, this won't work for a nested tree.
@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;
}
}
}
}
I'm planning to create my own FlatTreeControl
(by extending Angular CDK's FlatTreeControl
) and move this logic there.
UPDATE
I've moved the above logic to my own FlatTreeControl
implementation:
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;
}
}
}
}
Thanks to Flauwekeul, a little bit simplified
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;
}
}
}
}
Parent hierarchy can be stored in Array of numbers where each number is index of reccurent nested node. In order to expand tree on specified node I tried use previous examples, but eventually I decided make it that way:
1) ChangePath must be call every time we click on node:
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) Next, when tree collapses, we must call expand of every item in nodePath (when tree collapse in is caused by delete node we dont want expand it, so last element is removed from path):
expandTreeOnSpecifiedNode(isDelete: boolean) {
if (isDelete) {
this.nodePath.pop();
}
this.nodePath.forEach(id => {
console.log(id);
this.treeControl.expand(this.treeControl.dataNodes[id]);
});
}
© 2022 - 2024 — McMap. All rights reserved.