前提条件:嵌套可滚动div中的cdk可拖动元素 (请参见示例https://stackblitz.com/edit/angular-7y19nm?file=app/cdk-drag-drop-sorting-example.html)
如何复制:开始拖动项目->滚动页面->不滚动时再拖动项目
效果:项目占位符停留在错误的位置,基本上不可能将项目拖到视口之外的任何地方。
<div style="height: 100vh; overflow-y: auto">
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
<div class="example-box" *ngFor="let movie of movies" cdkDrag>{{movie}}</div>
</div>
</div>
答案 0 :(得分:0)
我已经在Angular components' official Github repository中搜索了此问题,并且发现了以下主题:
根据您使用的版本,有不同的解决方案: Angular 9 + (还可以与 Angular 10 一起使用)或 Angular 8 :
从版本 9.1.0 开始,可以通过将父元素设置为cdkScrollable
指令来支持父元素的滚动。
因此,对于v9.1.0及更高版本,以下代码应该有效:
<div style="height: 100vh; 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-yjiz7r (使用v10.0.1 )
https://stackblitz.com/edit/angular-vszdat(使用v9.2.4 )
从版本 8.1.0 开始,启用了滚动,但仅用于 cdkDropList本身或视口 >(出于性能原因)。因此,有两种解决方案:
overflow: scroll
设置为cdkDropList
元素:<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)" style="height: 100vh; overflow-y: auto">
<div class="example-box" *ngFor="let movie of movies" cdkDrag>{{movie}}
</div>
</div>
Stackblitz演示:
https://stackblitz.com/edit/angular-avezy6
cdkDropList
滚动,并且有一个父元素应该滚动(就像问题中的情况),我就改编了这里找到的解决方案( https://github.com/angular/components/issues/16677#issuecomment-562625427):
我们可以使用将在cdkDropListScrollContainer
元素上设置的自定义指令cdkDrag
。该指令将对应滚动的父元素的引用作为Input
:<div class="example-container" style="height: 500px; overflow-y: auto" #scrollContainer>
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
<div
class="example-box"
*ngFor="let movie of movies"
cdkDrag
[cdkDropListScrollContainer]="scrollContainer">
{{movie}}
</div>
</div>
</div>
该指令的代码为:
import { Directive, Input, ElementRef } from "@angular/core";
import { CdkDrag } from "@angular/cdk/drag-drop";
@Directive({
selector: "[cdkDropListScrollContainer]"
})
export class CdkDropListScrollContainerDirective {
@Input("cdkDropListScrollContainer") scrollContainer: HTMLElement;
originalElement: ElementRef<HTMLElement>;
constructor(cdkDrag: CdkDrag) {
cdkDrag._dragRef.beforeStarted.subscribe(() => {
const cdkDropList = cdkDrag.dropContainer;
if (!this.originalElement) {
this.originalElement = cdkDropList.element;
}
if (this.scrollContainer) {
const element = this.scrollContainer;
cdkDropList._dropListRef.element = element;
cdkDropList.element = new ElementRef<HTMLElement>(element);
} else {
cdkDropList._dropListRef.element = cdkDropList.element.nativeElement;
cdkDropList.element = this.originalElement;
}
});
}
}
Stackblitz演示: https://stackblitz.com/edit/angular-jkuqhg