From 0925cf58ce6a7c5bc10cea515445bcb5b03f77c4 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 12 Feb 2025 18:16:12 +0100 Subject: [PATCH] fix(material/timepicker): allow scroll strategy to be customized (#30473) Adds an injection token to the timepicker that allows the scroll strategy to be customized, similar to other components. Fixes #30421. --- src/material/timepicker/timepicker.ts | 18 ++++++++++++++++-- tools/public_api_guard/material/timepicker.md | 4 ++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/material/timepicker/timepicker.ts b/src/material/timepicker/timepicker.ts index 9d538213a793..c11b5cabc1d0 100644 --- a/src/material/timepicker/timepicker.ts +++ b/src/material/timepicker/timepicker.ts @@ -17,6 +17,7 @@ import { effect, ElementRef, inject, + InjectionToken, Injector, input, InputSignal, @@ -41,7 +42,7 @@ import { MatOptionParentComponent, } from '@angular/material/core'; import {Directionality} from '@angular/cdk/bidi'; -import {Overlay, OverlayRef} from '@angular/cdk/overlay'; +import {Overlay, OverlayRef, ScrollStrategy} from '@angular/cdk/overlay'; import {TemplatePortal} from '@angular/cdk/portal'; import {_getEventTarget} from '@angular/cdk/platform'; import {ENTER, ESCAPE, hasModifierKey, TAB} from '@angular/cdk/keycodes'; @@ -62,6 +63,18 @@ export interface MatTimepickerSelected { source: MatTimepicker; } +/** Injection token used to configure the behavior of the timepicker dropdown while scrolling. */ +export const MAT_TIMEPICKER_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>( + 'MAT_TIMEPICKER_SCROLL_STRATEGY', + { + providedIn: 'root', + factory: () => { + const overlay = inject(Overlay); + return () => overlay.scrollStrategies.reposition(); + }, + }, +); + /** * Renders out a listbox that can be used to select a time of day. * Intended to be used together with `MatTimepickerInput`. @@ -89,6 +102,7 @@ export class MatTimepicker implements OnDestroy, MatOptionParentComponent { private _defaultConfig = inject(MAT_TIMEPICKER_CONFIG, {optional: true}); private _dateAdapter = inject>(DateAdapter, {optional: true})!; private _dateFormats = inject(MAT_DATE_FORMATS, {optional: true})!; + private _scrollStrategyFactory = inject(MAT_TIMEPICKER_SCROLL_STRATEGY); protected _animationsDisabled = inject(ANIMATION_MODULE_TYPE, {optional: true}) === 'NoopAnimations'; @@ -321,7 +335,7 @@ export class MatTimepicker implements OnDestroy, MatOptionParentComponent { this._overlayRef = this._overlay.create({ positionStrategy, - scrollStrategy: this._overlay.scrollStrategies.reposition(), + scrollStrategy: this._scrollStrategyFactory(), direction: this._dir || 'ltr', hasBackdrop: false, }); diff --git a/tools/public_api_guard/material/timepicker.md b/tools/public_api_guard/material/timepicker.md index d5c868014967..be4b213cee8a 100644 --- a/tools/public_api_guard/material/timepicker.md +++ b/tools/public_api_guard/material/timepicker.md @@ -17,6 +17,7 @@ import { MatOptionParentComponent } from '@angular/material/core'; import { ModelSignal } from '@angular/core'; import { OnDestroy } from '@angular/core'; import { OutputEmitterRef } from '@angular/core'; +import { ScrollStrategy } from '@angular/cdk/overlay'; import { Signal } from '@angular/core'; import { TemplateRef } from '@angular/core'; import { ValidationErrors } from '@angular/forms'; @@ -25,6 +26,9 @@ import { Validator } from '@angular/forms'; // @public export const MAT_TIMEPICKER_CONFIG: InjectionToken; +// @public +export const MAT_TIMEPICKER_SCROLL_STRATEGY: InjectionToken<() => ScrollStrategy>; + // @public export class MatTimepicker implements OnDestroy, MatOptionParentComponent { constructor();