如何使树按需加载数据?我已经后端通过哪个方法为我返回了根节点,并通过父母id向我返回了父母的孩子。我想在树上单击节点并加载树数据,然后为我绘制带有子项的新分支,等等。我不知道这棵树有多深。如何用mat-tree实现它?我尝试了递归函数* ngFor,但不适用于mat-tree。我想要类似link的东西,但没有任何外部库
答案 0 :(得分:1)
好吧,我创建了具有两个功能的服务
getRootNodes(){}
和
getChildren(node:any){}
getRootNodes,返回第一级root。
getChildren(nodes:any),返回“孩子”。但是,不仅返回字符串数组,而且使它返回具有属性“ isExpandable”的对象数组。对于材料树,必须知道孩子何时生孩子
下一个更改是在DinamicDataSource中使用我们的服务。我们的toggleNode必须使用该服务。如果!expands是setTimeOut下的代码,那么,我们当然不需要setTimeOut。
如果expand = true,我们将调用该服务并订阅数据。在setTimeOut下INTO订阅代码。
请注意,在两种情况下,我们都需要调用this.dataChange.next(this.data)
toggleNode(node: DynamicFlatNode, expand: boolean) {
const index = this.data.indexOf(node);
if (!expand)
{
let count = 0;
for (let i = index + 1; i < this.data.length
&& this.data[i].level > node.level; i++, count++) {}
this.data.splice(index + 1, count);
this.dataChange.next(this.data);
}
else
{
node.isLoading = true;
this.dataService.getChildren(node.item).subscribe(children=>{
if (!children || index < 0) { // If no children, or cannot find the node, no op
node.isLoading = false;
return;
}
if (expand) {
const nodes = children.map(obj =>
new DynamicFlatNode(obj.name, node.level + 1, obj.isExpandable));
this.data.splice(index + 1, 0, ...nodes);
}
node.isLoading = false;
// notify the change
this.dataChange.next(this.data);
})
}
}
最后一个更改是传递给ngOnInit TreeDynamicExample中的构造函数
ngOnInit()
{
this.treeControl = new FlatTreeControl<DynamicFlatNode>(this.getLevel, this.isExpandable);
this.dataSource = new DynamicDataSource(this.treeControl, this.dataService);
this.dataService.getRootNodes().subscribe(res=>{
this.dataSource.data = res.map(name => new DynamicFlatNode(name, 0, true));
})
}
请注意,在将this.dataSourceData等同于DynamicFlatNode之前,我们需要获取数据并将其放入订阅
更新:使DinamicData源神秘化。
嗯,要了解树形结构,我们可以看一下DynamicData Source中的“数据”。这些数据只是具有以下属性的对象数组:item,level,expandable和loading。所以,看起来像
[
{item: "Fruits",level:0,expandable:true,isLoading:false},
{item: "Apple",level:1,expandable:true,isLoading:false},
{item: "Orange",level:1,expandable:false,isLoading:false},
{item: "Bannana",level:1,expandable:false,isLoading:false},
{item: "Vegetables",level:0,expandable:true,isLoading:false}
]
是的,这只是一个简单的数组。但这是一个有序的数组。因此,我们可以在DinamicDataSource中创建一个功能addNode,例如
addSubNode(index:number,name:string,isExpandable:boolean)
{
const node=this.data[index];
const dfn={item: name,
level:node.level+1,
expandable:isExpandable,
isLoading:false}
this.data.splice(index + 1, 0, ...[dfn]);
this.dataChange.next(this.data);
}
addNode(index:number,name:string,isExpandable:boolean)
{
const node=this.data[index];
const dfn={item: name,
level:node.level,
expandable:isExpandable,
isLoading:false}
this.data.splice(index + 1, 0, ...[dfn]);
this.dataChange.next(this.data);
}
changeNode(index:number,name:string)
{
this.data[index].item=name;
}
看到,在更改数组后-添加一个节点/子节点,我们需要调用this.dataChange.next(this.data),因为拼接可以更改数组的“内容”,但不能更改数组本身。我们还可以做一些“ bizarro”作为
this.data=[...this.data]
但是Angular Material的成员使我们的生活变得轻松,我们可以使用.next(这是因为数据实际上不是数组,而是BehaviorSubject的值)
我希望该声明消除动态树的“魔力”。我forked the stackblitz添加树形简单按钮以添加节点,添加子节点并更改节点