javascript - Angular CDK - 在嵌套的可滚​​动 div 内滚动和拖动元素的问题

标签 javascript html css angular angular-cdk

先决条件: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 中搜索过这个问题我发现了以下主题:

  • https://github.com/angular/components/issues/13588
  • https://github.com/angular/components/issues/16535

  • 根据您使用的版本,有不同的解决方案: 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: scrollcdkDropList元素:

  • <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/

    相关文章:

    javascript - 坚持使用 Javascript 的简单斐波那契数列

    javascript - 使用 JQPlot 绘制大型数据集

    javascript - html 图片上传不适用于 firefox

    javascript - 多次点击时显示多张图像

    javascript - 如何检查 dropzone 中是否已有图像?

    javascript - Travis-CI Node 构建随机失败

    javascript - 从同一函数中删除单个元素

    html - 使用 CSS,当用户将鼠标悬停在某个元素上时,如何向该元素添加圆形灰色背景

    javascript - 带有图像而不是标签的 MDL 单选按钮

    javascript - 每 2 秒的 iframe 高度 [动态]