从 angular 6 material 树中的子节点获取父层次结构
Get parent hierarchy from a child node in angular 6 material tree
我正在关注 tutorial 以在 angular 6 中实现 cdk 树。我创建了一个树结构,现在我想通过使其可点击来从子级获取父级层次结构,同时有像 getDescendants 这样的方法来获取节点的子节点,反之亦然。如何从子节点或叶节点获取父层次结构。
我已将这些方法添加到我的树组件中。请注意,我使用的是扁平树,这不适用于嵌套树。
@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;
}
}
}
}
感谢 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;
}
}
}
}
父层次结构可以存储在数字数组中,其中每个数字都是递归嵌套节点的索引。为了在指定节点上扩展树,我尝试使用以前的示例,但最终我决定这样做:
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]);
});
}
我正在关注 tutorial 以在 angular 6 中实现 cdk 树。我创建了一个树结构,现在我想通过使其可点击来从子级获取父级层次结构,同时有像 getDescendants 这样的方法来获取节点的子节点,反之亦然。如何从子节点或叶节点获取父层次结构。
我已将这些方法添加到我的树组件中。请注意,我使用的是扁平树,这不适用于嵌套树。
@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;
}
}
}
}
感谢 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;
}
}
}
}
父层次结构可以存储在数字数组中,其中每个数字都是递归嵌套节点的索引。为了在指定节点上扩展树,我尝试使用以前的示例,但最终我决定这样做:
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]);
});
}