Angular Drag and Drop cdk ... автопрокрутка в прокручиваемом div теряет DROP ZONE - PullRequest
1 голос
/ 18 февраля 2020

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

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

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

Хитрость заключается в том, что кажется, что функция автоматической прокрутки cdk Drag and Drop работает только из коробки по отношению либо ко всему размеру окна, либо, если это div с фиксированной высотой с overflow-y: scroll (именно это я и пытаюсь сделать), то это должно быть на уровне 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>

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

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 больше не позволяет мне бросать элемент в это положение массива ... элемент по-прежнему выглядит как DRAGGING, но это наводит меня на мысль, что он больше не распознает DROP ZONE

Heres What it looks like

...