Angular 8 和 Angular 材质:使用 CdkDropList 项拖动滚动

Posted

技术标签:

【中文标题】Angular 8 和 Angular 材质:使用 CdkDropList 项拖动滚动【英文标题】:Angular 8 & Angular Material: Drag Scrolling with CdkDropList item 【发布时间】:2020-04-05 08:51:20 【问题描述】:

我试图在拖动 cdkDropList 项目时提供滚动。截至目前,如果不使用鼠标滚轮滚动,页面将无法滚动。我希望能够根据列表项的拖动来滚动页面。谷歌搜索后,似乎直到几个月前才有可能?!

我在 angular material repo 中发现了以下提交: https://github.com/crisbeto/material2/commit/b4be85f6716a2d1a432ef7109aa06e7255324222

但尚未在 Angular Material 网站上找到任何文档。我很好奇自从发布以来是否有人使用 Angular Material 在 CdkDropList 元素上实现了任何自动拖动滚动。我对角度比较陌生。我已经尝试将 cdkScrollable 标记添加到 div 中,但是在拖动列表中的任何元素时能够使自动滚动功能起作用。

想法/建议?

【问题讨论】:

您可以尝试使用事件侦听器,例如当用户拖动到可滚动列表的底部附近时,如果用户拖动可滚动列表顶部附近的项目然后滚动到底部,则将列表滚动到底部顶部。 我想显然它应该自动为滚动工作。我想固定高度/宽度的布局/容器存在某种约束,我相信这是我发现的。 【参考方案1】:

9.1.0 版本开始,通过在应该滚动的父级上设置 cdkScrollable 指令来支持自动滚动。

因此,对于 v9.1.0 及更高版本,以下代码应该可以工作:

<div style="height: 500px; overflow-y: auto" cdkScrollable>
  <div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let movie of movies" cdkDrag>movie</div>
  </div>
</div>

Stackblitz 演示

https://stackblitz.com/edit/angular-swaqkk-njehwg (使用 Angular CDK v10.0.1

另外,我在以下主题中发布了一个更完整的答案,其中包括更多示例以及 Angular8 的解决方案: Angular CDK - issue with scrolling and dragging element inside nested scrollable div

【讨论】:

必须有一个固定的高度,以 px 或 % 为单位才能正常工作。 默认速度不好用。不要忘记 cdkDropList [cdkDropListAutoScrollDisabled]="false" [cdkDropListAutoScrollStep]="35" 的 API 详细信息【参考方案2】:

注意:cdkScrollable 不会神奇地让任何东西滚动。您必须构建订阅和操作来处理事件。

关于 cdkDropList,如果子元素包含 *ngFor 以及要循环的项目,它将滚动。修改了@andreivictor 的answer 来证明这一点:https://stackblitz.com/edit/angular-swaqkk-4iaqwc?file=src%2Fapp%2Fcdk-drag-drop-sorting-example.html

<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
    <div *ngFor="let movie of movies" >
    <ng-container *ngTemplateOutlet="Tmpl2; context: movieT: movie ">
    </ng-container>
</div>
<ng-template #Tmpl2 let-movieT="movieT">
    <div>
                <div class="example-box" cdkDrag>movieT</div>
    </div>
</ng-template>

将 ngFor div 移动到模板中并将 movieT 重命名为 movie,您将看到滚动停止。这是因为 cdkDropList 指令不能再访问另一个组件内的项目。我不知道有什么方法可以处理这种情况,但是如果您可以避免使用模板,我想滚动应该可以按预期工作。如果您要嵌套列表,这也是一个问题。我无法让cdkDropListGroup attribute 工作,但添加id 属性并使用cdkDropListConnectedTo 数组属性(在同一链接上找到)效果很好。

【讨论】:

它确实可以滚动,只要具有cdkScrollable 的元素具有固定高度。 你能证明这一点吗?我发现测试和删除 cdkScrollable 没有相关性,或者原始答案的 stackblitz 中的样式对滚动没有影响。 当我实现这个时,没有“滚动事件处理程序”只是cdkScrollable - ibb.co/QF47N79 - 就像其他答案所说的那样。直到我为我想要滚动的容器设置了一个高度,它才起作用【参考方案3】:

只是将我的研究结合到一个答案中。深入了解D&D API 的存在。

  <div #boardWrapper class="board-wrapper" cdkScrollable>
    <!-- cdkDropListGroup when multiple droplists -->    
    <div #boardColumns class="board-columns" cdkDropListGroup>
      <!-- A drop list -->
      <div
        cdkDropList
        [cdkDropListAutoScrollDisabled]="false" <-- enable
        [cdkDropListAutoScrollStep]="35"        <-- speed
        [cdkDropListData]="data.arr"
        (cdkDropListDropped)="drop($event)"
      >
        <!-- A drag item -->
        <div
          cdkDrag
          [cdkDragData]="item.data"
          (cdkDragMoved)="onDragMoved($event)"
          (cdkDragStarted)="dragStarted($event)"
        >content</div>
      </div>
    </div>
  </div>

【讨论】:

以上是关于Angular 8 和 Angular 材质:使用 CdkDropList 项拖动滚动的主要内容,如果未能解决你的问题,请参考以下文章

Angular > 在材质表中显示列和行

Angular2 材质“md-icon”不是已知元素

如何使用 angular5 和 angular 材质创建自定义颜色主题

Angular2 材质 npm 依赖项

Angular 2 材质和 flex-layout 对齐

使用 Angular CLI 的 Angular 2 材质