先决条件:cdk 嵌套可滚动元素内的可拖动元素div
(见 example )
如何重现:
效果:元素占位符停留在错误的位置,基本上不可能将元素拖动到视口(viewport)之外的任何地方。
<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>
最佳答案
我在 Angular components' official Github repository 中搜索过这个问题我发现了以下主题:
根据您使用的版本,有不同的解决方案: Angular 9+ (也适用于 Angular 10 )或 Angular 8 :
Angular 9+(也适用于 Angular 10)
从版本 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)
Angular 8
从版本 8.1.0 ,滚动已启用,但 仅限 对于 cdkDropList 本身 或 视口(viewport) (出于性能原因)。所以有两种解决方案:
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
关于javascript - Angular CDK - 在嵌套的可滚动 div 内滚动和拖动元素的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57755127/