【问题标题】:Reposition CdkConnectedOverlay on scroll在滚动时重新定位 CdkConnectedOverlay
【发布时间】:2019-06-25 00:06:42
【问题描述】:

我正在尝试使用CdkConnectedOverlay 在单击按钮时显示叠加层。它大部分都在工作,但覆盖不会在滚动上重新定位。我确定我遗漏了一些小东西,但我终生无法弄清楚。

我正在使用Angular 7.2.8Angular CDK 7.3.3

认为这可能与缺少 cdk 样式有关(类似于 this),但我导入了这些;如果样式丢失,我希望它一开始就不能正确显示。我的只是没有在滚动上重新定位。

模板:

<button
  (click)="isOpen = !isOpen"
  cdkOverlayOrigin
  #trigger="cdkOverlayOrigin"
>Show</button>

<ng-template
  cdkConnectedOverlay
  [cdkConnectedOverlayOrigin]="trigger"
  [cdkConnectedOverlayOpen]="isOpen"
>
 Popover content
</ng-template>

组件:

@Component ( {
  selector: 'app-popover',
  templateUrl: './popover.component.html',
  styleUrls: [ './popover.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush,
} )
export class PopoverComponent {
  isOpen: boolean = false;
}

还有一个显示问题的 Plunkr: https://stackblitz.com/edit/angular-7-popover

更新

仅当弹出框位于使用overflow: auto 溢出其父级的元素中时,才会出现滚动重新定位问题。如果页面溢出,那么它工作正常。您可以使用以下模板查看此行为

<div style="height: 300px; overflow-y: auto">
  <!-- Scroll re-positioning does not work when scrolling in here -->
  <div style="height: 100px"></div>
  <app-popover>
    Popover content
  </app-popover>
  <div style="height: 400px"></div>
</div>

<div style="height: 100px;"></div>
<!-- Scroll re-positioning works when scrolling here -->
<app-popover>
  Popover content
</app-popover>
<div style="height: 1200px;"></div>

我还更新了 stackblitz 以显示此问题。

【问题讨论】:

    标签: angular-cdk


    【解决方案1】:

    cdk 文档有时不容易理解,而且到处都是隐藏的宝石:)

    here 它声明;

    每个策略通常会注入 ScrollDispatcher(来自 @angular/cdk/scrolling),以便在滚动发生时得到通知。

    我从这句话中了解到Overlay 重新定位自己以响应来自ScrollDispatcher 的事件。那么,这些滚动事件是从哪里来的呢?

    不幸的是,文档中没有关于此的任何信息。于是我看了一下代码,发现this

      /** Sets up the global scroll listeners. */
      private _addGlobalListener() {
        this._globalSubscription = this._ngZone.runOutsideAngular(() => {
          return fromEvent(window.document, 'scroll').subscribe(() => this._scrolled.next());
        });
    }
    

    这意味着ScrollDispatcher默认监听窗口上的滚动事件

    在您上面的例子中,它在窗口滚动而不是内部容器时响应事件。这符合我们目前收集到的信息。

    在这里我们可以得出结论,Overlay 不会被通知内部容器内发生的滚动事件,我们需要做的就是向ScrollDispatcher 注册内部容器

    此时cdkScrollable 指令进入救援状态,将cdkScrollable 放置在滚动的内部容器上即可解决问题。

    <div cdkScrollable style="height: 300px; overflow-y: auto">
    

    这是一个有效的demo

    【讨论】:

    • 啊,现在说得通了!大约在您发布此答案的同时,我也在 Github 上遇到了这个问题,这基本上是在说同样的事情。 github.com/angular/components/issues/6157
    • 对于那些需要它的人,为了让cdkScrollable工作,你需要导入ScrollingModule。 import {ScrollingModule} from '@angular/cdk/scrolling'; ..... imports: [ ....., ScrollingModule]
    猜你喜欢
    • 1970-01-01
    • 2021-12-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 2014-02-09
    • 1970-01-01
    相关资源
    最近更新 更多