问题
I'm new to angular material drag and drop.
My app is using an n-ary tree, and since I don't know its form apriori, I've been forced to use a recursive template in order to represent it.
The last couple of days I've been trying to use Angular material drag and drop to reorder siblings. If I remove the root node everything works just fine, but I cannot remove the root node since I need it to traverse the tree for other operations.
Bellow is a simplified form of the tree. In reality, the tree can have many more branches and leaves, but I wanted to keep it simple.
Json of the n-ary tree (root node with the 3 children nodes I want to be able to drag and drop):
[
{
"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
}
]
Component:
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);
}
}
Template code:
<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>
Also: How can I know the Node being dragged and the node it was dropped after? I haven't been able to find an answer anywhere but if I can get these two I might be able to solve it by traversing the tree and doing everything by hand.
Thanks in advance and for getting this far and reading the whole question.
回答1:
You may use the HTML5 drag and drop. Its working fine with angular2+. Reference Link https://www.w3schools.com/html/html5_draganddrop.asp
回答2:
In case some is going through the same problem... I solved this issue passing the node dragged to the drop method by using [cdkDragData]=node since cdk drag and drop is designed for lists, not n-ary trees.
<div [cdkDragData]=node *ngFor="let node of tree; let i=index " cdkDrag>
Then, inside the method one can traverse the tree and do the changes "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
Thanks for the answers I received, it really encouraged me to find the best solution 😊
来源:https://stackoverflow.com/questions/59711702/angular-drag-and-drop-not-working-when-dropping-elements-in-n-ary-tree-represent