Реализация перетаскивания в дереве материалов Angular - узел гнезда при наведении другого узла - PullRequest
0 голосов
/ 02 мая 2020

Этот вопрос неоднократно поднимался на SO, но не в последнее время, и приведенный здесь пример является более полным, чем другие, которые я видел. Лучшая реализация перетаскивания с деревом материалов - это , размещенное здесь на среде @ @ 1003 * inorganik .

Я клонировал StackBlitz здесь.

Однако моя проблема в том, что вы можете перемещать узлы, только если у вас есть хотя бы один дочерний элемент на узле. Например, если вы удалите все дочерние узлы из приложения, а затем попытаетесь добавить его обратно в приложение.

Отброшенный узел будет вставлен в родительский узел только в том случае, если у узла есть братья и сестры, в строке 232:

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

Мне кажется логичным, что решение будет отслеживать, если пользователь перемещал перемещенный узел над другим узлом, когда они его отбрасывали, а затем предположил, что пользователь хочет сделать подчиненный узел родительским, см. снимок экрана:

angular material drag and drop tree

Мой вопрос: это лучший способ go решить эту проблему? Если да, то как отследить зависший узел с помощью Angular Drag Drop CDK?

ОБНОВЛЕНИЕ:

Эта функция частично работает. Я обновил StackBlitz здесь.

Я обновил dragHover метод, основанный на других реализациях мат-дерева 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);
    }
  }

Я добавил это к методу drop. Если dragNodeInsertToParent равно true, найдите индекс узла в месте назначения отбрасывания и pu sh узел, который нужно вставить в его дочерний массив.

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

Теперь, если вы вытащите узел достаточно далеко вправо, включится режим вставки, и вы сможете добавить дочерний элемент обратно в пустой родительский узел:

animated gif of node being removed from and added to parent

В любом случае, все еще продолжая работать над этим, если у кого-то есть какие-либо идеи для того, чтобы сделать эту работу более интуитивно, пожалуйста, оставьте комментарий.

...