From d2aeb8b369ce523914db8e32295595035481b564 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 6 May 2024 21:28:15 +0200 Subject: [PATCH] fix(cdk/menu): allow for scroll strategy to be configured (#29005) Adds an injection token that allows users to configure the scroll strategy of a CDK menu. Fixes #28965. --- src/cdk/menu/context-menu-trigger.ts | 2 +- src/cdk/menu/menu-trigger-base.ts | 17 ++++++++++++++++- src/cdk/menu/menu-trigger.ts | 2 +- tools/public_api_guard/cdk/menu.md | 5 +++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/cdk/menu/context-menu-trigger.ts b/src/cdk/menu/context-menu-trigger.ts index 6b6d0f7d1cca..93db6f5d4754 100644 --- a/src/cdk/menu/context-menu-trigger.ts +++ b/src/cdk/menu/context-menu-trigger.ts @@ -139,7 +139,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr private _getOverlayConfig(coordinates: ContextMenuCoordinates) { return new OverlayConfig({ positionStrategy: this._getOverlayPositionStrategy(coordinates), - scrollStrategy: this._overlay.scrollStrategies.reposition(), + scrollStrategy: this.menuScrollStrategy(), direction: this._directionality || undefined, }); } diff --git a/src/cdk/menu/menu-trigger-base.ts b/src/cdk/menu/menu-trigger-base.ts index 0bafe5d7ba5d..e8ed063b86d7 100644 --- a/src/cdk/menu/menu-trigger-base.ts +++ b/src/cdk/menu/menu-trigger-base.ts @@ -18,13 +18,25 @@ import { } from '@angular/core'; import {Menu} from './menu-interface'; import {MENU_STACK, MenuStack} from './menu-stack'; -import {ConnectedPosition, OverlayRef} from '@angular/cdk/overlay'; +import {ConnectedPosition, Overlay, OverlayRef, ScrollStrategy} from '@angular/cdk/overlay'; import {TemplatePortal} from '@angular/cdk/portal'; import {merge, Subject} from 'rxjs'; /** Injection token used for an implementation of MenuStack. */ export const MENU_TRIGGER = new InjectionToken('cdk-menu-trigger'); +/** Injection token used to configure the behavior of the menu when the page is scrolled. */ +export const MENU_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>( + 'cdk-menu-scroll-strategy', + { + providedIn: 'root', + factory: () => { + const overlay = inject(Overlay); + return () => overlay.scrollStrategies.reposition(); + }, + }, +); + /** * Abstract directive that implements shared logic common to all menu triggers. * This class can be extended to create custom menu trigger types. @@ -46,6 +58,9 @@ export abstract class CdkMenuTriggerBase implements OnDestroy { /** The menu stack in which this menu resides. */ protected readonly menuStack: MenuStack = inject(MENU_STACK); + /** Function used to configure the scroll strategy for the menu. */ + protected readonly menuScrollStrategy = inject(MENU_SCROLL_STRATEGY); + /** * A list of preferred menu positions to be used when constructing the * `FlexibleConnectedPositionStrategy` for this trigger's menu. diff --git a/src/cdk/menu/menu-trigger.ts b/src/cdk/menu/menu-trigger.ts index 09860f7b736c..4250be2152d9 100644 --- a/src/cdk/menu/menu-trigger.ts +++ b/src/cdk/menu/menu-trigger.ts @@ -249,7 +249,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy { private _getOverlayConfig() { return new OverlayConfig({ positionStrategy: this._getOverlayPositionStrategy(), - scrollStrategy: this._overlay.scrollStrategies.reposition(), + scrollStrategy: this.menuScrollStrategy(), direction: this._directionality || undefined, }); } diff --git a/tools/public_api_guard/cdk/menu.md b/tools/public_api_guard/cdk/menu.md index 8a57756a4e9c..6ed34d1b0ea7 100644 --- a/tools/public_api_guard/cdk/menu.md +++ b/tools/public_api_guard/cdk/menu.md @@ -22,6 +22,7 @@ import { OnDestroy } from '@angular/core'; import { Optional } from '@angular/core'; import { OverlayRef } from '@angular/cdk/overlay'; import { QueryList } from '@angular/core'; +import { ScrollStrategy } from '@angular/cdk/overlay'; import { Subject } from 'rxjs'; import { TemplatePortal } from '@angular/cdk/portal'; import { TemplateRef } from '@angular/core'; @@ -225,6 +226,7 @@ export abstract class CdkMenuTriggerBase implements OnDestroy { isOpen(): boolean; menuData: unknown; menuPosition: ConnectedPosition[]; + protected readonly menuScrollStrategy: () => ScrollStrategy; protected readonly menuStack: MenuStack; menuTemplateRef: TemplateRef | null; // (undocumented) @@ -296,6 +298,9 @@ export interface Menu extends MenuStackItem { // @public export const MENU_AIM: InjectionToken; +// @public +export const MENU_SCROLL_STRATEGY: InjectionToken<() => ScrollStrategy>; + // @public export const MENU_STACK: InjectionToken;