这个问题在 SO 上已经被多次提出,但不是最近,而且这里的例子比我见过的其他例子更完整。使用材质树进行拖放的最佳实现是@inorganik在媒体上发布的这个。
但是,我的问题是,如果节点上至少有一个子元素,则只能移动节点。例如,如果您从 Application 中删除所有子节点,然后尝试将其添加回 Application。
如果节点有兄弟节点,则删除的节点只会插入到父节点中,第 232 行:
// insert node
const newSiblings = findNodeSiblings(changedData, nodeAtDest.id);
if (!newSiblings) return;
newSiblings.splice(relativeIndex, 0, nodeToInsert);
在我看来,解决方案是跟踪用户是否将移动的节点悬停在另一个节点上,然后假设用户想要将悬停的节点设为父节点,这对我来说似乎是合乎逻辑的,请参阅屏幕截图:
我的问题是:这是解决这个问题的最好方法吗?如果是这样,如何使用 Angular Drag Drop CDK 跟踪悬停的节点?
更新:
我已经让这个功能部分工作了。我在这里更新了 StackBlitz。
我根据 mat-tree DnD 的其他实现更新了该dragHover
方法,我发现它根据用户将悬停的节点向右拖动多远来设置插入模式:
dragHover(node: FileFlatNode) {
// untype the event
const newEvent: any = event;
const percentageX = newEvent.offsetX / newEvent.target.clientWidth;
if (percentageX > .25) {
this.dragNodeInsertToParent = true;
} else {
this.dragNodeInsertToParent = false;
}
if (this.dragging) {
clearTimeout(this.expandTimeout);
this.expandTimeout = setTimeout(() => {
this.treeControl.expand(node);
}, this.expandDelay);
}
}
我将此添加到drop
方法中。如果dragNodeInsertToParent
是true
,则找到放置目标节点的索引,并将节点推送到其子数组中。
if (this.dragNodeInsertToParent) {
const indexOfParent = newSiblings.findIndex( element => element.id === nodeAtDest.id);
newSiblings[indexOfParent].children.push(nodeToInsert);
} else {
newSiblings.splice(relativeIndex, 0, nodeToInsert);
}
现在,如果您将节点拉出足够远的右侧,则会触发插入模式,您可以将子节点添加回空的父节点:
无论如何,仍在努力,如果有人有任何想法让这项工作更直观,请发表评论。