Вложенное перетаскивание с помощью Angular 7 Material CDK - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть вложенное дерево (не компонент дерева) перетаскиваемых списков.

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

Сейчас я думаю, что лучшим решением будет подавление событий, запускаемых для списка контейнеров, если в данный момент перетаскивание происходит по внутреннему списку, но я не уверен, является ли это лучшим решением или как именно это сделать намомент.

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Проблема с этим решением заключается в том, что предикат не влияет на уже продолжающееся перетаскивание в CdkDropList, где оно было создано.

Это проблема, потому что при перемещении объектов «вверх» иерархия работает (из-за функции предиката), перемещение, например, одного элемента под своим братом, «вниз» в иерархии вызывает неизбежное перекрытие 2 областей CdkDropLists, что приведет к результат в состоянии гонки.

Это основная проблема, требующая решения - как произвольно сказать родительскому CdkDropList «прекратить учитывать» CdkDrag (реагирующий на перетаскивание), в то же время имея возможность эффективно отбросить его в дочернем CdkDropList

Или другими словами - получить все списки CdkDropList, проколотые по оси Z X, Y помеченные позицией указателя, выбрать один с наименьшей площадью («младшая») и сделать остальные «не реагирующими» на текущее перетаскивание.

0 голосов
/ 13 ноября 2018

Мне удалось найти решение этой проблемы, хотя оно определенно хакерское и предполагает доступ к закрытому значению с помощью Angular drag and drop CDK.

Я использую функцию cdkDropListEnterPredicate, чтобы проверить, в какой список следует пытаться попасть, и назначить функцию canDropPredicate.

Я также вынужден получить доступ к позиции указателя через: _pointerPositionAtLastDirectionChange, который невелик, поскольку не все значения, которые я хотел бы видеть, переданные в cdkDropListEnterPredicate, будут переданы.

canDropPredicate(): Function {
    const me = this;
    return (drag: CdkDrag<ResourceNode>, drop: CdkDropList<ResourceNode>): boolean => {
        const fromBounds = drag.dropContainer.element.nativeElement.getBoundingClientRect();
        const toBounds = drop.element.nativeElement.getBoundingClientRect();

        if (!me.intersect(fromBounds, toBounds)) {
            return true;
        }

        // This gross but allows us to access a private field for now.
        const pointerPosition: Point = drag['_dragRef']['_pointerPositionAtLastDirectionChange'];
        // They Intersect with each other so we need to do some calculations here.
        if (me.insideOf(fromBounds, toBounds)) {
          return !me.pointInsideOf(pointerPosition, fromBounds);
        }

        if (me.insideOf(toBounds, fromBounds) && me.pointInsideOf(pointerPosition, toBounds)) {
          return true;
        }
         return false;
    };
}

intersect(r1: DOMRect | ClientRect, r2: DOMRect | ClientRect): boolean {
    return !(r2.left > r1.right ||
        r2.right < r1.left ||
        r2.top > r1.bottom ||
        r2.bottom < r1.top);
}

insideOf(innerRect: DOMRect | ClientRect, outerRect: DOMRect | ClientRect): boolean {
    return innerRect.left >= outerRect.left &&
        innerRect.right <= outerRect.right &&
        innerRect.top >= outerRect.top &&
        innerRect.bottom <= outerRect.bottom &&
        !(
            innerRect.left === outerRect.left &&
            innerRect.right === outerRect.right &&
            innerRect.top === outerRect.top &&
            innerRect.bottom === outerRect.bottom
        );
}

pointInsideOf(position: Point, rect: DOMRect | ClientRect) {
  return position.x >= rect.left &&
        position.x <= rect.right &&
        position.y >= rect.top &&
        position.y <= rect.bottom;
}
...