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 项拖动滚动的主要内容,如果未能解决你的问题,请参考以下文章