Отмена перетаскивания на нажатие клавиши Angular CDK Drag and Drop
Я работаю в приложении, реализующем новое перетаскивание из углового материала 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>
Ц компонент
onDragEnded(event: CdkDragEnd) {
console.log(event)
event.source.element.nativeElement.style.transform = 'none';
const source: any = event.source;
source._passiveTransform = { x: 0, y: 0 };
}
но пока безуспешно.
3 ответа
Я тоже давно сталкивался с этой проблемой. Наконец я мог это исправить, отправив mouseup
событие, которое будет действовать как пользователь, отпустивший мышь.
@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
if (event.key === 'Escape') {
document.dispatchEvent(new Event('mouseup'));
}
}
Это чрезвычайно хакерское решение, которое имеет свои недостатки. На самом деле, вы не отменяете перетаскивание, а просто отбрасываете. Это означает, что если вы зависаете cdkDropList
или один активен, это вызовет cdkDropListDropped
Emmiter для этого списка. Что-то, что вы можете легко обойти, добавив флаг.
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
}
}
Надеюсь, это поможет вам...:)
Вы можете переместить перетаскиваемый элемент в позицию, используя:
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};
Лучший способ сделать это - позвонить event.source._dragRef.reset();
(как @AleRubis упомянул в комментарии) на ESC
нажатие клавиши. Теперь вопрос в том, откуда вы можете получить этот _dragRef вне событий cdkDrag (ESC
ключевое событие), вы можете сохранить его в такой переменной компонента при запуске перетаскивания.
Составная часть:
cdkDragStarted = (event) => {
this.dragRef = event.source._dragRef;
}
Шаблон:
<p cdkDrag (cdkDragStarted)="cdkDragStarted($event)">
Draggable paragraph
</p>
Вот версия с использованием rxjs. Требуется ссылка наCdkDrag
как ViewChild. К сожалению, поскольку нет общедоступного метода, чтобы остановить перетаскиваниеDragRef
ты должен использовать dispatchEvent
как единственный способ завершить процесс перетаскивания.
В приведенном ниже примере есть две части. Что происходит, так это то, что завершенное событие можно прослушать только после начала, и этот экземпляр прослушивания может быть остановлен субъектом, запущенным нажатием escape.
- В AfterViewInit создается подписка на запущенный EventEmitter из
CdkDrag
директива. - После события запуска поток, который переключается на прослушивание, завершился.
- Если запрос отмены запущен, поток будет завершен
takeUntil
оператор иreset()
будет вызвана директива для сброса позиции иdispatchEvent()
будет использоваться для остановки процесса перетаскивания. - В противном случае после запуска конечного события
onDragEnded()
метод вызывается из OP. - Если не происходит чего-то действительно забавного, завершенное событие будет запускаться не более одного раза за запуск, поэтому нет необходимости в дополнительных
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();
}
}
Вы можете использовать что-то вроде...
@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
if (event.code === 'Escape') {
// call dragend event
}
}