Отменить перетаскивание при нажатии клавиши Angular cdk Перетаскивание

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

Шаблон

<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
  <div class="example-box" *ngFor="let movie of movies" (cdkDragEnded)="onDragEnded($event)" cdkDrag>{{movie}}</div>
</div>

Компонент Ts

onDragEnded(event: CdkDragEnd) {
  console.log(event)
  event.source.element.nativeElement.style.transform = 'none';
  const source: any = event.source;
  source._passiveTransform = { x: 0, y: 0 };
}

но пока безуспешно.


person Miguel Frias    schedule 04.12.2018    source источник
comment
Вы решили это? Спасибо, Э.   -  person Eusthace    schedule 08.12.2018
comment
к сожалению, пока нет ....   -  person Miguel Frias    schedule 10.12.2018
comment
Чтобы сбросить перетаскиваемый элемент в исходное положение, вместо того, чтобы вручную устанавливать преобразование элемента и source._passiveTransform, теперь вы можете выполнить event.source._dragRef.reset();   -  person AleRubis    schedule 13.06.2019


Ответы (5)


Тоже долго сталкивался с этой проблемой. Наконец, я мог исправить это, отправив событие mouseup, которое будет действовать как пользователь, отпускающий мышь.

@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
    if (event.key === 'Escape') {
        document.dispatchEvent(new Event('mouseup'));
    }
}

Это чрезвычайно хакерское решение, и у него есть свои недостатки. Фактически, вы не отменяете перетаскивание, а вместо этого опускаетесь. Это означает, что если вы наводите курсор на cdkDropList или один активен, он запускает cdkDropListDropped эмитент для этого списка. Что-то, что можно легко обойти, добавив флаг.

private _canceledByEsq = false;

@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
    if (event.key === 'Escape') {
        this._canceledByEsq = true;
        document.dispatchEvent(new Event('mouseup'));
    }
}

handleDrop() {
    if (!this._canceledByEsq) {
        // Do my data manipulations
    }
}

Надеюсь, это поможет вам ... :)

person danizep    schedule 24.01.2019

Вы можете переместить перетаскиваемый элемент в позицию, используя:

event['source']['element']['nativeElement']['style']['transform'] = 'translate3d(0,0,0)';
event['source']['_dragRef']['_activeTransform'] = {x: 0, y: 0};
event['source']['_dragRef']['_passiveTransform'] = {x: 0, y: 0};
person Alessio Pragliola - Creact    schedule 17.01.2019

Лучший способ сделать это - вызвать event.source._dragRef.reset(); (как @AleRubis упоминается в комментарии) при нажатии клавиши ESC. Теперь вопрос в том, откуда вы можете получить этот _dragRef вне событий cdkDrag (ESC ключевое событие), вы можете сохранить его в такой переменной компонента, когда начнется перетаскивание.

Составная часть:

cdkDragStarted = (event) => { this.dragRef = event.source._dragRef; }

Шаблон:

<p cdkDrag (cdkDragStarted)="cdkDragStarted($event)"> Draggable paragraph </p>

person Ubaid Ur Rehman    schedule 06.11.2019
comment
У меня не получилось. DragRef.reset (), похоже, ничего не делает (проверено с Angular 9.1.X). Таким образом, я предпочитаю решение @danizep. - person LittleWhite; 12.03.2020

Вот версия с использованием rxjs. Требуется ссылка на CdkDrag как на ViewChild. К сожалению, поскольку не существует общедоступного метода прекращения перетаскивания DragRef, вы должны использовать dispatchEvent как единственный способ завершить процесс перетаскивания.

В приведенном ниже примере есть две части. Что происходит, так это то, что событие завершено можно прослушивать только после начала, и этот экземпляр прослушивания может быть остановлен субъектом, инициированным нажатием клавиши escape.

  • В AfterViewInit создается подписка на запущенный EventEmitter из директивы CdkDrag.
  • После события запуска поток, который переключается на прослушивание , закончился.
  • Если запрос отмены запущен, поток будет завершен оператором takeUntil, и reset() будет вызываться в директиве для сброса позиции, а dispatchEvent() будет использоваться для остановки процесса перетаскивания.
  • В противном случае после запуска конечного события из OP вызывается метод onDragEnded().
  • Если не происходит чего-то действительно забавного, событие завершено будет запускаться не более одного раза за запуск, поэтому нет необходимости в дополнительном take(1).
private dragCancelRequest = new Subject();

ngAfterViewInit() {
  this.drag.started.pipe(
    switchMap(({ source }) => source.ended.pipe(
      takeUntil(this.dragCancelRequest.pipe(tap(() => {
        source.reset();
        document.dispatchEvent(new Event('mouseup'));
      })))
    )),
    tap(x => this.onDragEnded(x))
  ).subscribe();
}

@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
  if (event.key === 'Escape') {
    this.dragCancelRequest.next();
  }
}
person Daniel Gimenez    schedule 23.06.2020

Вы можете использовать что-то вроде ...

@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
    if (event.code === 'Escape') {
        // call dragend event
    }
}
person R. Viral    schedule 04.12.2018
comment
Хорошо, я могу проверить нажатие клавиши, но как мне сбросить элемент, перетащенный в исходное положение, и отменить перетаскивание. - person Miguel Frias; 04.12.2018
comment
вы можете запомнить положение x и y в переменной в событии начала перетаскивания - person R. Viral; 04.12.2018
comment
это не является конкретным, и вопрос в том, как отменить событие перетаскивания после начала перетаскивания, которое запускается для мыши при нажатии клавиши. - person Miguel Frias; 04.12.2018
comment
во время перетаскивания такого элемента с любым событием вы можете получить его фактическую позицию и использовать эту позицию во время отмены .. это полезно, если вы создаете стек для своей проблемы. - person R. Viral; 04.12.2018
comment
Хорошо, вопрос в том, как отменить событие перетаскивания, а не в том, как вернуть перетаскиваемый элемент в исходное положение, только отменив событие перетаскивания, элемент вернет исходную позицию без запоминания положения x или y, поэтому вопрос в том, как отменить перетаскивание элемент - начало перетаскивания. - person Miguel Frias; 04.12.2018
comment
Здесь у вас есть ссылка, по которой вы можете показать мне в коде, как это сделать, потому что пока в этом коде вы отменяете только событие мыши, событие перетаскивания все еще работает: [Drag & drop] stackblitz.com/edit/angular-deufx5 - person Miguel Frias; 04.12.2018