Angular 在使用递归模板表示的 n 元树中拖放元素时,拖放不起作用
Angular drag and drop not working when dropping elements in n-ary tree represented using recursive template
我是 angular material 拖放新手。
我的应用程序使用的是 n 叉树,由于我不知道它的先验形式,我不得不使用递归模板来表示它。
最近几天我一直在尝试使用 Angular material 拖放来重新排序兄弟姐妹。如果我删除根节点,一切正常,但我无法删除根节点,因为我需要它遍历树以进行其他操作。
波纹管是树的简化形式。其实这棵树可以有更多的枝叶,但我想保持简单。
n叉树的Json(我希望能够拖放的带有3个子节点的根节点):
[
{
"orderIndex": 0,
"id": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"parentId": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"name": "Interface1",
"conditions": "None",
"text": null,
"description": "description",
"children": [
{
"orderIndex": 0,
"id": "5a4f87ce-c527-4cc1-b587-22898ded5cc0",
"parentId": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"name": "Interface2",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
},
{
"orderIndex": 1,
"id": "5a4f87ce-c527-4cc8-b587-26898ded5cc0",
"parentId": "5a4f87ce-c527-4cc8-b587-23898ded5cc0",
"name": "Interface6",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
},
{
"orderIndex": 2,
"id": "5a4f87ce-c525-4cc1-b587-25898ded5cc0",
"parentId": "5a4f87ce-c52e-4cc1-b587-24898ded5cc0",
"name": "Interface4",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
}
],
"errors": null
}
]
组件:
import { DataService } from './../data.service';
import { Node } from '../_Models/Node';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
@Component({
selector: 'app-vnf-main',
templateUrl: './vnf-main.component.html',
styleUrls: ['./vnf-main.component.css']
})
export class VnfMainComponent implements OnInit {
tree: Node[];
constructor(private dataService: DataService) {
}
ngOnInit() {
this.dataService.tree$.subscribe(result => {
this.tree = result;
});
drop(event: CdkDragDrop<Node[]>) {
moveItemInArray(this.tree, event.previousIndex, event.currentIndex);
}
}
模板代码:
<table>
<ng-template #recursiveList let-tree>
<div cdkDropList (cdkDropListDropped)="drop($event)">
<div *ngFor="let node of tree; let i=index " cdkDrag>
<tr>
<app-default-node [node]="node"></app-default-node>
<td *ngIf="node.children!==null && node.children.length > 0" cdkDrag>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: node.children }"></ng-container>
</td>
</tr>
</div>
</div>
</ng-template>
</table>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: tree }"></ng-container>
另外:我怎么知道被拖动的节点和它被拖到哪个节点之后?我无法在任何地方找到答案,但如果我能得到这两个答案,我也许可以通过遍历树并手动完成所有操作来解决它。
在此先感谢您走到这一步并阅读了整个问题。
万一有些人遇到同样的问题...我解决了这个问题,通过使用 [cdkDragData]=node 将节点拖动到 drop 方法,因为 cdk 拖动和drop 是为列表设计的,而不是 n-ary 树。
<div [cdkDragData]=node *ngFor="let node of tree; let i=index " cdkDrag>
然后,在方法内部可以遍历树并进行更改 "by hand":
const movedNode: Node = event.item.data; //Node that was dragged
const parentNode: Node = this.dataService.findNode(movedNode.parentId, this.tree[0]); //parent of the dragged node
moveItemInArray(parentNode.children, event.previousIndex, event.currentIndex); //move the node as in any other cdk drag and drop list
感谢我收到的答复,它确实鼓励我找到最佳解决方案
我是 angular material 拖放新手。
我的应用程序使用的是 n 叉树,由于我不知道它的先验形式,我不得不使用递归模板来表示它。
最近几天我一直在尝试使用 Angular material 拖放来重新排序兄弟姐妹。如果我删除根节点,一切正常,但我无法删除根节点,因为我需要它遍历树以进行其他操作。
波纹管是树的简化形式。其实这棵树可以有更多的枝叶,但我想保持简单。
n叉树的Json(我希望能够拖放的带有3个子节点的根节点):
[
{
"orderIndex": 0,
"id": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"parentId": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"name": "Interface1",
"conditions": "None",
"text": null,
"description": "description",
"children": [
{
"orderIndex": 0,
"id": "5a4f87ce-c527-4cc1-b587-22898ded5cc0",
"parentId": "5a4f87ce-c52d-4cc1-b587-21898ded5cc0",
"name": "Interface2",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
},
{
"orderIndex": 1,
"id": "5a4f87ce-c527-4cc8-b587-26898ded5cc0",
"parentId": "5a4f87ce-c527-4cc8-b587-23898ded5cc0",
"name": "Interface6",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
},
{
"orderIndex": 2,
"id": "5a4f87ce-c525-4cc1-b587-25898ded5cc0",
"parentId": "5a4f87ce-c52e-4cc1-b587-24898ded5cc0",
"name": "Interface4",
"conditions": "None",
"text": null,
"description": "description",
"children": [],
"errors": null
}
],
"errors": null
}
]
组件:
import { DataService } from './../data.service';
import { Node } from '../_Models/Node';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
@Component({
selector: 'app-vnf-main',
templateUrl: './vnf-main.component.html',
styleUrls: ['./vnf-main.component.css']
})
export class VnfMainComponent implements OnInit {
tree: Node[];
constructor(private dataService: DataService) {
}
ngOnInit() {
this.dataService.tree$.subscribe(result => {
this.tree = result;
});
drop(event: CdkDragDrop<Node[]>) {
moveItemInArray(this.tree, event.previousIndex, event.currentIndex);
}
}
模板代码:
<table>
<ng-template #recursiveList let-tree>
<div cdkDropList (cdkDropListDropped)="drop($event)">
<div *ngFor="let node of tree; let i=index " cdkDrag>
<tr>
<app-default-node [node]="node"></app-default-node>
<td *ngIf="node.children!==null && node.children.length > 0" cdkDrag>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: node.children }"></ng-container>
</td>
</tr>
</div>
</div>
</ng-template>
</table>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: tree }"></ng-container>
另外:我怎么知道被拖动的节点和它被拖到哪个节点之后?我无法在任何地方找到答案,但如果我能得到这两个答案,我也许可以通过遍历树并手动完成所有操作来解决它。
在此先感谢您走到这一步并阅读了整个问题。
万一有些人遇到同样的问题...我解决了这个问题,通过使用 [cdkDragData]=node 将节点拖动到 drop 方法,因为 cdk 拖动和drop 是为列表设计的,而不是 n-ary 树。
<div [cdkDragData]=node *ngFor="let node of tree; let i=index " cdkDrag>
然后,在方法内部可以遍历树并进行更改 "by hand":
const movedNode: Node = event.item.data; //Node that was dragged
const parentNode: Node = this.dataService.findNode(movedNode.parentId, this.tree[0]); //parent of the dragged node
moveItemInArray(parentNode.children, event.previousIndex, event.currentIndex); //move the node as in any other cdk drag and drop list
感谢我收到的答复,它确实鼓励我找到最佳解决方案