在 Angular Material 树中实现拖放 - 当另一个节点悬停时嵌套节点

Meq*_*qwz 5 javascript angular-material angular angular-cdk angular-cdk-drag-drop

这个问题已经在 SO 上多次提出,但不是最近,这里的例子比我见过的其他例子更完整。拖放用材质树的最好的FPGA实现是这样的一个张贴在这里的媒体通过@ inorganik

我在这里克隆了 StackBlitz。

但是,我的问题是只有在节点上至少有一个子元素时才能移动节点。例如,如果您从 Application 中删除所有子节点,然后尝试将其添加回 Application。

如果节点有兄弟节点,则删除的节点只会插入到父节点中,在第 232 行:

    // insert node 
    const newSiblings = findNodeSiblings(changedData, nodeAtDest.id);
    if (!newSiblings) return;
    newSiblings.splice(relativeIndex, 0, nodeToInsert);
Run Code Online (Sandbox Code Playgroud)

对我来说,解决方案是跟踪用户在放下移动节点时是否将其悬停在另一个节点上似乎合乎逻辑,然后假设用户希望将悬停节点设为父节点,请查看屏幕截图:

角材料拖放树

我的问题是:这是解决这个问题的最佳方法吗?如果是这样,如何使用 Angular Drag Drop CDK 跟踪悬停的节点?

更新:

我已经让这个功能部分工作了。我在这里更新了StackBlitz。

dragHover根据我发现的 mat-tree DnD 的其他实现更新了该方法,它根据用户将悬停节点拖动到右侧的距离设置插入模式:

  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);
    }
  }
Run Code Online (Sandbox Code Playgroud)

我将此添加到drop方法中。如果dragNodeInsertToParenttrue,则在 drop 的目的地找到节点的索引,并将节点推送到其子数组中。

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

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

从父节点中删除和添加节点的动画 gif

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