Angular Drag and Drop cdk auto-scroll в прокручиваемом div теряет DROP ZONE

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

КРАТКАЯ ВЕРСИЯ

  1. cdk dnd не будет автоматически прокручиваться
  2. сделал свой автопрокрутку
  3. cdk dnd не выпадает после прокрутки

Хитрость в том, что, похоже, функция автоматической прокрутки cdk Drag and Drop работает только из коробки в отношении либо всего размера окна, либо, если это div с фиксированной высотой с overflow-y: scroll (это то, что я пытаюсь to do), то это должно быть на уровне cdkDropList. К сожалению, из-за компонентной архитектуры моего приложения в настоящее время это НЕ вариант.

Я написал свою собственную функцию автопрокрутки, которая прокручивает div в зависимости от положения мыши на экране во время перетаскивания элемента, у меня это работает, но большая проблема заключается в том, что как только div начинает прокрутку вы теряете возможность оставить элемент в списке.

Вот HTML-код моего родительского компонента (div с фиксированной высотой и положением переполнения)

<div #ScrollDiv style="height: 200px; width: 200px; overflow-y: scroll; padding: 5px;">
  <app-child (itemSelected)="itemSelection($event)"></app-child>
</div>

Вот шаблон дочернего компонента с директивами cdk

   <div cdkDropList style="border: 2px solid purple;" (cdkDropListDropped)="drop($event)">
    <div cdkDrag [cdkDragData]="draggers" *ngFor="let item of draggers; let i = index"
            style="height: 30px; border: 2px solid blue; margin: 5px"
            (mousedown)="grabDrag()">
            {{item}}</div>   
    </div>

На этом этапе я могу перетащить в свое окно, но автопрокрутка не работает, поэтому я добавил автопрокрутку в файл Type Script родительского компонента, изменив положение прокрутки на (mousemove). Для позиций для начала прокрутки вверх / вниз значения жестко запрограммированы на странице, с которой я работаю.

import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, ChangeDetectionStrategy } from '@angular/core';
import { Subscription, fromEvent } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit  {
  title = 'drag-sizing';
  itemSelected = false;
  isScrolling = false;
  smoothScroll;
  scrollSpeed = 2;
  @ViewChild('ScrollDiv', {static: true}) public myScrollContainer: ElementRef;

ngAfterViewInit() {
  fromEvent(this.myScrollContainer.nativeElement, 'mousemove').subscribe((event: MouseEvent) => {
    if (this.itemSelected) {
      if (event.clientY < 150) {
        this.isScrolling = true;
        if (!this.smoothScroll) {
          this.smoothScroll = setInterval(() => {
            this.scrollUp();
          }, 10);
        }
      } else if (event.clientY > 300) {
        this.isScrolling = true;
        if (!this.smoothScroll) {
          this.smoothScroll = setInterval(() => {
            this.scrollDown();
          }, 10);
        }
      } else {
        clearInterval(this.smoothScroll);
        this.smoothScroll = undefined;
        this.isScrolling = false;
      }
    } else {
      clearInterval(this.smoothScroll);
      this.smoothScroll = undefined;
      this.isScrolling = false;
    }
  });
}
  scrollInner() {
    this.myScrollContainer.nativeElement.scrollTop += 2;
  }
  itemSelection(event) {
    this.itemSelected = event;
    if (!this.itemSelected) {
      clearInterval(this.smoothScroll);
      this.smoothScroll = undefined;
    }
  } 
  scrollUp() {
    if (this.isScrolling === true) {
      this.myScrollContainer.nativeElement.scrollTop -= this.scrollSpeed;
    }
  }

  scrollDown() {
    if (this.isScrolling === true) {
      this.myScrollContainer.nativeElement.scrollTop += this.scrollSpeed;
    }
  }
}

и дочерний компонент TypeScript, который излучает, что элемент перетаскивается и имеет функцию перетаскивания

import { Component, OnInit, Input, ElementRef, ViewChild, AfterViewInit, Output, EventEmitter } from '@angular/core';
import { Subscription, fromEvent, BehaviorSubject, Subject } from 'rxjs';
import { CdkDragDrop, transferArrayItem, moveItemInArray } from '@angular/cdk/drag-drop';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements  AfterViewInit {
@Output() itemSelected = new EventEmitter<boolean>();

  itemIsSelected = false;
  draggers = ['item 0', 'item 1', 'item 2'...]

  ngAfterViewInit(): void {
    fromEvent(document, 'mouseup').subscribe(() => {
      this.itemIsSelected = false;
      this.itemSelected.emit(this.itemIsSelected);
  });
  }
  grabDrag() {
    this.itemIsSelected = true;
    this.itemSelected.emit(this.itemIsSelected);
  }
  drop(event: CdkDragDrop<any>) {
    console.log(event);
    moveItemInArray(this.draggers, event.previousIndex, event.currentIndex);
  }
}

(могут быть некоторые вещи, которые я не использую, оставшиеся после неудачных попыток)

В любом случае: я знаю, что это было долго, но основное поведение, которое я пытаюсь преодолеть / выяснить, это Когда я перетаскиваю элемент и прокручиваю от небольшого фрагмента массива в его исходном порту просмотра, перетаскивание cdk больше не позволяет мне бросать элемент в эту позицию массива ... элемент все еще кажется ПЕРЕТАСКИВАЮЩИМ, но это наводит меня на мысль, что он больше не распознает ЗОНУ ВЫПАДЕНИЯ.

Вот как это выглядит


person Alexander Hardy    schedule 18.02.2020    source источник


Ответы (1)


Я думаю, что решение могло бы заключаться в том, чтобы поместить директиву cdkScrollable в контейнер, внутри которого есть компоненты, с помощью перетаскивания CDK.

person Miroslav    schedule 19.06.2020
comment
У меня это сработало - пришлось положить его во внешний контейнер. - person Sean Chase; 03.11.2020
comment
Спасибо, у меня тоже работает - person Sumskyi Vasyl; 28.12.2020
comment
Все еще пытаетесь это исправить, у кого-нибудь мало кодов? - person Kalhan.Toress; 09.03.2021