在滚动上重新放置CdkConnectedOverlay

时间:2019-06-25 00:06:42

标签: angular-cdk

我正在尝试使用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>

我还更新了堆栈闪电以显示此问题。

1 个答案:

答案 0 :(得分:0)

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