5

这个问题在 SO 上已经被多次提出,但不是最近,而且这里的例子比我见过的其他例子更完整。使用材质树进行拖放的最佳实现是@inorganik在媒体上发布的这个

我在这里克隆了 StackBlitz。

但是,我的问题是,如果节点上至少有一个子元素,则只能移动节点。例如,如果您从 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方法中。如果dragNodeInsertToParenttrue,则找到放置目标节点的索引,并将节点推送到其子数组中。

    if (this.dragNodeInsertToParent) {
      const indexOfParent = newSiblings.findIndex( element => element.id === nodeAtDest.id);
      newSiblings[indexOfParent].children.push(nodeToInsert);
    } else {
      newSiblings.splice(relativeIndex, 0, nodeToInsert);
    }

现在,如果您将节点拉出足够远的右侧,则会触发插入模式,您可以将子节点添加回空的父节点:

从父节点移除并添加到父节点的动画 gif

无论如何,仍在努力,如果有人有任何想法让这项工作更直观,请发表评论。

4

0 回答 0