在滚动条上重新定位 CdkConnectedOverlay
Reposition CdkConnectedOverlay on scroll
我正在尝试使用 CdkConnectedOverlay
在单击按钮时显示叠加层。它主要是工作,但覆盖不会在滚动上重新定位。我确定我遗漏了一些小东西,但我一辈子都弄不明白。
我正在使用 Angular 7.2.8
和 Angular 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 以显示此问题。
cdk 文档有时不太容易理解,而且到处都是隐藏的宝石:)
here 它指出;
Each strategy will typically inject ScrollDispatcher (from @angular/cdk/scrolling) to be notified of when scrolling takes place.
我从这句话中了解到,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
默认监听 window 上的滚动事件.
在您上面的例子中,当 window 滚动但不是内部容器时,它会响应事件。这符合我们目前收集到的信息。
这里我们可以得出结论,Overlay
不会收到内部容器内发生的滚动事件的通知,我们需要做的就是向 ScrollDispatcher
[=23= 注册内部容器]
此时 cdkScrollable 指令可以解决问题,将 cdkScrollable
放在滚动的内部容器上即可解决问题。
<div cdkScrollable style="height: 300px; overflow-y: auto">
这是一个有效的 demo
我正在尝试使用 CdkConnectedOverlay
在单击按钮时显示叠加层。它主要是工作,但覆盖不会在滚动上重新定位。我确定我遗漏了一些小东西,但我一辈子都弄不明白。
我正在使用 Angular 7.2.8
和 Angular 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 以显示此问题。
cdk 文档有时不太容易理解,而且到处都是隐藏的宝石:)
here 它指出;
Each strategy will typically inject ScrollDispatcher (from @angular/cdk/scrolling) to be notified of when scrolling takes place.
我从这句话中了解到,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
默认监听 window 上的滚动事件.
在您上面的例子中,当 window 滚动但不是内部容器时,它会响应事件。这符合我们目前收集到的信息。
这里我们可以得出结论,Overlay
不会收到内部容器内发生的滚动事件的通知,我们需要做的就是向 ScrollDispatcher
[=23= 注册内部容器]
此时 cdkScrollable 指令可以解决问题,将 cdkScrollable
放在滚动的内部容器上即可解决问题。
<div cdkScrollable style="height: 300px; overflow-y: auto">
这是一个有效的 demo