取消按键上的拖动Angular CDK拖放

时间:2018-12-04 09:05:33

标签: javascript angular angular-material angular-cdk

我正在一个应用程序中实现从角材料CDK进行新的拖放操作,我试图取消按ng serve --aot 的元素的拖动事件,我的意思是,我开始拖动该元素,但是如果我在拖动元素时按Esc,它应该回到我开始拖动它的位置,到目前为止,我还没有找到执行此操作的方法,有人知道我该怎么做。 cdk文档中没有关于此任何想法的任何内容。我尝试做这样的事情。

模板

Esc

Ts组件

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

但到目前为止没有成功。

5 个答案:

答案 0 :(得分:2)

我也长期面对这个问题。最后,我可以通过调度Unhandled Exception: System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first. 事件来解决该问题,该事件将充当用户释放鼠标的作用。

mouseup

这是一个非常hacky的解决方案,它具有缺点。实际上,您并不是在取消拖动,而是取消拖动。这意味着,如果您将鼠标悬停在@HostListener('window:keyup', ['$event']) handleKeyboardEvent(event: KeyboardEvent) { if (event.key === 'Escape') { document.dispatchEvent(new Event('mouseup')); } } 上,或者它处于活动状态,则会触发该列表的cdkDropList发射器。您可以通过添加标记轻松解决此问题。

cdkDropListDropped

希望这对您有帮助...:)

答案 1 :(得分:1)

这是使用rxjs的版本。它需要引用CdkDrag作为ViewChild。不幸的是,由于没有停止在DragRef上拖动的公共方法,因此必须使用dispatchEvent作为结束拖动过程的唯一方法。

在下面的示例中有两个部分。发生了什么事,结束事件只能在开始之后才能收听,并且该收听实例可以由按ESC键触发的主题停止。

  • 在AfterViewInit中,从CdkDrag指令创建到 started EventEmitter的订阅。
  • 在开始事件之后,流将切换为收听结束
  • 如果触发了取消请求,则流将由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();
  }
}

答案 2 :(得分:0)

您可以使用以下方法将拖动的项目移动到某个位置:

print

答案 3 :(得分:0)

最好的方法是在event.source._dragRef.reset();按键上调用ESC(如评论中提到的@AleRubis)。 现在的问题是,从哪里可以在cdkDrag事件(ESC键事件)之外获取_dragRef,可以在拖动开始时将其保存在这样的组件变量中。

组件:

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

模板:

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

答案 4 :(得分:-2)

您可以使用类似...

@HostListener('window:keyup', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
    if (event.code === 'Escape') {
        // call dragend event
    }
}