如何使用cdkDragHandle使垫子表的行拖放工作,以便只能使用手柄拖动该行?

时间:2019-03-06 16:53:11

标签: angular typescript angular-material angular-cdk

我发现了this的使用闪电cdk将拖放添加到mat-table的stackblitz示例。但是,所需的行为是该行只能使用带有cdkDragHandle指令的元素进行拖动。在此示例中,您可以通过单击行上的任意位置来拖动元素。该如何修改,以使该行只能使用拖动手柄进行拖动?

https://stackblitz.com/edit/angular-igmugp

7 个答案:

答案 0 :(得分:4)

这是我针对此问题的解决方法:

  1. 设置布尔值以控制是否应禁用cdkDrag。默认行为已禁用。
  2. mousedown添加mouseuptouchstarttouchendcdkDragHandle事件处理程序以切换控件。
  3. cdkDrag中,监听cdkDragReleased事件以将cdkDrag拖动后禁用。

副作用是,使用真正要禁用的项目变得更加困难(例如,对那些真正禁用的项目应用样式)。

代码如下:

  • 组件类
  dragDisabled = true;
  • cdkDrag
<mat-row
  *matRowDef="let row; columns: displayedColumns"
  cdkDrag
  [cdkDragData]="row"
  [cdkDragDisabled]="dragDisabled"
  (cdkDragReleased)="dragDisabled = true"
></mat-row>
  • cdkDragHandle
<mat-icon
  cdkDragHandle
  (touchstart)="dragDisabled = false"
  (touchend)="dragDisabled = true"
  (mousedown)="dragDisabled = false"
  (mouseup)="dragDisabled = true"
  >drag_indicator</mat-icon
>

答案 1 :(得分:1)

恕我直言,除了破解/覆盖Angular Material / CDK的源代码外,没有其他快速解决方案。对此的证明是在github上的开放功能请求:https://github.com/angular/material2/issues/13770

问题在于,数据源/ MatTable上的cdkDrag会在所有子元素上自动创建拖动注释(这会生成行为),并且无法(轻松)覆盖。

基于文档cdkDrag/cdkDragDisabled-cdkDragHandle/cdkDragHandleDisabled应该有所帮助(它确实可以在没有表的情况下工作)。我已经升级了示例中的所有库以支持它们,但没有任何效果。

答案 2 :(得分:1)

对于这个复杂的问题,我发现了一个简单的问题。对于可拖动tr中的任何简单文本td,我们可以使用指标事件:无,它将禁用所有文本元素。

在手柄图标上,使用pointer-events:all,它将仅允许从该图标拖动。

这还有一个问题,它禁用了所有锚点和按钮。因此,对于图标和按钮,进行以下操作

  1. 使用mouseDown设置标志
  2. 在拖动开始时,检查拖放mouseup事件
  3. 在拖动停止时,检查是否设置了标志并重置标志并返回

检查此stackblits的有效答案 https://stackblitz.com/edit/angular-rwzc76

答案 3 :(得分:1)

我在这里有一个替代答案(以前可能不可能) - 它结合了 @H Dog@Mamoon ur Rasheed 的答案。

根据 H Dog 的回答,将拖动手柄移动到单元格本身而不是行中,并使用 cdkDragRootElement 选择父垫行。但是,这仍然使整行可拖动。

接下来,默认禁用拖动,绑定到组件上的布尔值。当在拖动手柄上触发 mousedown 事件时,启用拖动,然后在下一帧中再次禁用它。

这使得整行允许正常交互,但允许通过具有适当占位符和预览功能的拖动手柄拖动。

答案 4 :(得分:0)

我通过将Vectors do not all have the same length. SNP LDL-c.beta LDL-c.se CHD.beta CHD.se 1 snp_10 1 0.004 2 0.0286 2 snp_10 1 0.004 2 0.0300 3 snp_10 1 0.004 2 0.0310 4 snp_10 1 0.003 2 0.0243 5 snp_10 1 0.003 2 0.0222 6 snp_10 1 0.006 2 0.0667 应用于dragHandle本身而不是行,并使用cdkDrag来标识该行,从而实现了UX。它可以实现通过手柄拖动的UX,但是仍然存在一个错误,无法在放下后实际重新排序。

See Stackblitz here.

Documentation of cdkDragRootElement is here.

Here is link to Github issue about it.

答案 5 :(得分:0)

对于这里发布的解决方案,我有另一种解决方案。除了链接和纯文本单元格需要更多的交互性(包括文本选择,输入字段等)外,我还有一个要求。

使用将在cdkDrag表行(tr)中呈现的所有不可拖动单元格上的指令,我能够阻止mousedown事件冒泡到cdkDrag实例的有效cdkDropList行。

这是我的指令最终看起来像的样子。

import {Directive, ElementRef, OnDestroy, OnInit} from '@angular/core';

@Directive({
  selector: '[appCancelCdkDrag]'
})
export class CancelCdkDrag implements OnInit, OnDestroy {
  $element: HTMLElement;

  constructor(el: ElementRef) {
    this.$element = el.nativeElement;
  }

  fireMouseUp($event: MouseEvent) {
    $event.cancelBubble = true;
  }

  ngOnDestroy(): void {
    this.$element.removeEventListener('mousedown', this.fireMouseUp);
  }

  ngOnInit(): void {
    this.$element.addEventListener('mousedown', this.fireMouseUp);
  }

}

此处的StackBlitz:https://stackblitz.com/edit/angular-tgrcni

以下是有关Github Angular Components页面的相关评论:https://github.com/angular/components/issues/13770#issuecomment-553193486

希望这会有所帮助。

答案 6 :(得分:0)

这是一个仅按特定列开始拖动行的示例:

在组件上创建一个变量

dragEnabled = false;

将行设置为可拖动并通过变量禁用拖动

<mat-row *matRowDef="let row; columns: columns;" cdkDrag [cdkDragDisabled]="!dragEnabled">
</mat-row>

通过鼠标事件控制特定列上的dragEnabled变量状态

<ng-container matColumnDef="drag">
  <mat-header-cell *matHeaderCellDef>
  </mat-header-cell>
  <mat-cell *matCellDef="let entity"
            (mouseenter)="dragEnabled = true"
            (mouseleave)="dragEnabled = false">
    <mat-icon>
      drag_indicator
    </mat-icon>
  </mat-cell>
</ng-container>

现在您可以选择行内容并仅按特定列拖动行。