From c61a1cc7218c68a036e90bd11e61975741720ffc Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 15 May 2018 19:30:13 +0200 Subject: [PATCH] fix(overlay): injection errors for scroll strategy providers in lazy-loaded modules Fixes injection errors being thrown by the overlay-based providers that have injection tokens for the default scroll strategy. The error comes from the fact that the scroll strategies were being provided at the root, whereas the `Overlay` provider was provided normally, causing it to be missing when a module is lazy-loaded. Fixes #10820. --- src/cdk/overlay/overlay-directives.ts | 25 ++++++-------------- src/cdk/overlay/overlay-module.ts | 5 +++- src/lib/autocomplete/autocomplete-module.ts | 6 ++++- src/lib/autocomplete/autocomplete-trigger.ts | 16 +++++++------ src/lib/datepicker/datepicker-module.ts | 7 +++++- src/lib/datepicker/datepicker.ts | 16 +++++++------ src/lib/dialog/dialog.ts | 9 ++----- src/lib/menu/menu-module.ts | 6 ++++- src/lib/menu/menu-trigger.ts | 16 +++++++------ src/lib/tooltip/tooltip-module.ts | 8 +++++-- src/lib/tooltip/tooltip.ts | 16 +++++++------ 11 files changed, 71 insertions(+), 59 deletions(-) diff --git a/src/cdk/overlay/overlay-directives.ts b/src/cdk/overlay/overlay-directives.ts index 3a9c074fc3dd..31dc2340c378 100644 --- a/src/cdk/overlay/overlay-directives.ts +++ b/src/cdk/overlay/overlay-directives.ts @@ -10,16 +10,13 @@ import {Direction, Directionality} from '@angular/cdk/bidi'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {ESCAPE} from '@angular/cdk/keycodes'; import {TemplatePortal} from '@angular/cdk/portal'; -import {ScrollDispatcher, ViewportRuler} from '@angular/cdk/scrolling'; import { Directive, ElementRef, EventEmitter, Inject, - inject, InjectionToken, Input, - NgZone, OnChanges, OnDestroy, Optional, @@ -74,20 +71,12 @@ const defaultPositionList: ConnectedPosition[] = [ /** Injection token that determines the scroll handling while the connected overlay is open. */ export const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('cdk-connected-overlay-scroll-strategy', { - providedIn: 'root', - factory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_FACTORY, -}); + new InjectionToken<() => ScrollStrategy>('cdk-connected-overlay-scroll-strategy'); -/** @docs-private */ -export function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - // Store the injected deps here because we can't use the `inject` function outside - // this function's context (including the inner function). - const scrollDispatcher = inject(ScrollDispatcher); - const viewportRuler = inject(ViewportRuler); - const ngZone = inject(NgZone); - return (config?: RepositionScrollStrategyConfig) => - new RepositionScrollStrategy(scrollDispatcher, viewportRuler, ngZone, config); +/** @docs-private @deprecated @deletion-target 7.0.0 */ +export function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_FACTORY(overlay: Overlay): + () => ScrollStrategy { + return (config?: RepositionScrollStrategyConfig) => overlay.scrollStrategies.reposition(config); } /** @@ -394,13 +383,13 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { } -/** @docs-private @deprecated @deletion-target 7.0.0 */ +/** @docs-private */ export function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay: Overlay): () => RepositionScrollStrategy { return () => overlay.scrollStrategies.reposition(); } -/** @docs-private @deprecated @deletion-target 7.0.0 */ +/** @docs-private */ export const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = { provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY, deps: [Overlay], diff --git a/src/cdk/overlay/overlay-module.ts b/src/cdk/overlay/overlay-module.ts index 513692578603..d10c320bd797 100644 --- a/src/cdk/overlay/overlay-module.ts +++ b/src/cdk/overlay/overlay-module.ts @@ -25,7 +25,10 @@ import {OverlayPositionBuilder} from './position/overlay-position-builder'; imports: [BidiModule, PortalModule, ScrollDispatchModule], exports: [CdkConnectedOverlay, CdkOverlayOrigin, ScrollDispatchModule], declarations: [CdkConnectedOverlay, CdkOverlayOrigin], - providers: [Overlay], + providers: [ + Overlay, + CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER, + ], }) export class OverlayModule {} diff --git a/src/lib/autocomplete/autocomplete-module.ts b/src/lib/autocomplete/autocomplete-module.ts index 9e92a246a041..dde04874ab89 100644 --- a/src/lib/autocomplete/autocomplete-module.ts +++ b/src/lib/autocomplete/autocomplete-module.ts @@ -11,7 +11,10 @@ import {CommonModule} from '@angular/common'; import {OverlayModule} from '@angular/cdk/overlay'; import {MatOptionModule, MatCommonModule} from '@angular/material/core'; import {MatAutocomplete} from './autocomplete'; -import {MatAutocompleteTrigger} from './autocomplete-trigger'; +import { + MatAutocompleteTrigger, + MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER, +} from './autocomplete-trigger'; import {MatAutocompleteOrigin} from './autocomplete-origin'; @NgModule({ @@ -24,5 +27,6 @@ import {MatAutocompleteOrigin} from './autocomplete-origin'; MatCommonModule ], declarations: [MatAutocomplete, MatAutocompleteTrigger, MatAutocompleteOrigin], + providers: [MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER], }) export class MatAutocompleteModule {} diff --git a/src/lib/autocomplete/autocomplete-trigger.ts b/src/lib/autocomplete/autocomplete-trigger.ts index 9ca2210b4c16..752156580ee6 100644 --- a/src/lib/autocomplete/autocomplete-trigger.ts +++ b/src/lib/autocomplete/autocomplete-trigger.ts @@ -26,7 +26,6 @@ import { forwardRef, Host, Inject, - inject, InjectionToken, Input, NgZone, @@ -62,17 +61,20 @@ export const AUTOCOMPLETE_PANEL_HEIGHT = 256; /** Injection token that determines the scroll handling while the autocomplete panel is open. */ export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('mat-autocomplete-scroll-strategy', { - providedIn: 'root', - factory: MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY, - }); + new InjectionToken<() => ScrollStrategy>('mat-autocomplete-scroll-strategy'); /** @docs-private */ -export function MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - const overlay = inject(Overlay); +export function MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy { return () => overlay.scrollStrategies.reposition(); } +/** @docs-private */ +export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER = { + provide: MAT_AUTOCOMPLETE_SCROLL_STRATEGY, + deps: [Overlay], + useFactory: MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY, +}; + /** * Provider that allows the autocomplete to register as a ControlValueAccessor. * @docs-private diff --git a/src/lib/datepicker/datepicker-module.ts b/src/lib/datepicker/datepicker-module.ts index 4e90808a72ba..c0e08d6a75cf 100644 --- a/src/lib/datepicker/datepicker-module.ts +++ b/src/lib/datepicker/datepicker-module.ts @@ -15,7 +15,11 @@ import {MatButtonModule} from '@angular/material/button'; import {MatDialogModule} from '@angular/material/dialog'; import {MatCalendar, MatCalendarHeader} from './calendar'; import {MatCalendarBody} from './calendar-body'; -import {MatDatepicker, MatDatepickerContent} from './datepicker'; +import { + MatDatepicker, + MatDatepickerContent, + MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER, +} from './datepicker'; import {MatDatepickerInput} from './datepicker-input'; import {MatDatepickerIntl} from './datepicker-intl'; import {MatDatepickerToggle, MatDatepickerToggleIcon} from './datepicker-toggle'; @@ -61,6 +65,7 @@ import {MatYearView} from './year-view'; ], providers: [ MatDatepickerIntl, + MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER, ], entryComponents: [ MatDatepickerContent, diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 9c7bcf026121..3d7ae9f4bd60 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -27,7 +27,6 @@ import { ElementRef, EventEmitter, Inject, - inject, InjectionToken, Input, NgZone, @@ -51,17 +50,20 @@ let datepickerUid = 0; /** Injection token that determines the scroll handling while the calendar is open. */ export const MAT_DATEPICKER_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('mat-datepicker-scroll-strategy', { - providedIn: 'root', - factory: MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY, - }); + new InjectionToken<() => ScrollStrategy>('mat-datepicker-scroll-strategy'); /** @docs-private */ -export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - const overlay = inject(Overlay); +export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy { return () => overlay.scrollStrategies.reposition(); } +/** @docs-private */ +export const MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER = { + provide: MAT_DATEPICKER_SCROLL_STRATEGY, + deps: [Overlay], + useFactory: MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY, +}; + // Boilerplate for applying mixins to MatDatepickerContent. /** @docs-private */ export class MatDatepickerContentBase { diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts index d0b1e85d4f5a..3467c66bb5cf 100644 --- a/src/lib/dialog/dialog.ts +++ b/src/lib/dialog/dialog.ts @@ -18,7 +18,6 @@ import {ComponentPortal, ComponentType, PortalInjector, TemplatePortal} from '@a import {Location} from '@angular/common'; import { Inject, - inject, Injectable, InjectionToken, Injector, @@ -42,14 +41,10 @@ export const MAT_DIALOG_DEFAULT_OPTIONS = /** Injection token that determines the scroll handling while the dialog is open. */ export const MAT_DIALOG_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('mat-dialog-scroll-strategy', { - providedIn: 'root', - factory: MAT_DIALOG_SCROLL_STRATEGY_FACTORY, - }); + new InjectionToken<() => ScrollStrategy>('mat-dialog-scroll-strategy'); /** @docs-private */ -export function MAT_DIALOG_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - const overlay = inject(Overlay); +export function MAT_DIALOG_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy { return () => overlay.scrollStrategies.block(); } diff --git a/src/lib/menu/menu-module.ts b/src/lib/menu/menu-module.ts index 65a433613091..66e76040336e 100644 --- a/src/lib/menu/menu-module.ts +++ b/src/lib/menu/menu-module.ts @@ -13,7 +13,10 @@ import {MatCommonModule, MatRippleModule} from '@angular/material/core'; import {MatMenuContent} from './menu-content'; import {MatMenu} from './menu-directive'; import {MatMenuItem} from './menu-item'; -import {MatMenuTrigger} from './menu-trigger'; +import { + MatMenuTrigger, + MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER, +} from './menu-trigger'; @NgModule({ @@ -25,5 +28,6 @@ import {MatMenuTrigger} from './menu-trigger'; ], exports: [MatMenu, MatMenuItem, MatMenuTrigger, MatMenuContent, MatCommonModule], declarations: [MatMenu, MatMenuItem, MatMenuTrigger, MatMenuContent], + providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER] }) export class MatMenuModule {} diff --git a/src/lib/menu/menu-trigger.ts b/src/lib/menu/menu-trigger.ts index 885c828834ed..40b6d6616d7d 100644 --- a/src/lib/menu/menu-trigger.ts +++ b/src/lib/menu/menu-trigger.ts @@ -25,7 +25,6 @@ import { ElementRef, EventEmitter, Inject, - inject, InjectionToken, Input, OnDestroy, @@ -44,17 +43,20 @@ import {MenuPositionX, MenuPositionY} from './menu-positions'; /** Injection token that determines the scroll handling while the menu is open. */ export const MAT_MENU_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('mat-menu-scroll-strategy', { - providedIn: 'root', - factory: MAT_MENU_SCROLL_STRATEGY_FACTORY, - }); + new InjectionToken<() => ScrollStrategy>('mat-menu-scroll-strategy'); /** @docs-private */ -export function MAT_MENU_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - const overlay = inject(Overlay); +export function MAT_MENU_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy { return () => overlay.scrollStrategies.reposition(); } +/** @docs-private */ +export const MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER = { + provide: MAT_MENU_SCROLL_STRATEGY, + deps: [Overlay], + useFactory: MAT_MENU_SCROLL_STRATEGY_FACTORY, +}; + /** Default top padding of the menu panel. */ export const MENU_PANEL_TOP_PADDING = 8; diff --git a/src/lib/tooltip/tooltip-module.ts b/src/lib/tooltip/tooltip-module.ts index 448888c76329..444bafae2356 100644 --- a/src/lib/tooltip/tooltip-module.ts +++ b/src/lib/tooltip/tooltip-module.ts @@ -10,8 +10,11 @@ import {OverlayModule} from '@angular/cdk/overlay'; import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {MatCommonModule} from '@angular/material/core'; -import {MatTooltip, TooltipComponent} from './tooltip'; - +import { + MatTooltip, + TooltipComponent, + MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER, +} from './tooltip'; @NgModule({ imports: [ @@ -22,5 +25,6 @@ import {MatTooltip, TooltipComponent} from './tooltip'; exports: [MatTooltip, TooltipComponent, MatCommonModule], declarations: [MatTooltip, TooltipComponent], entryComponents: [TooltipComponent], + providers: [MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER] }) export class MatTooltipModule {} diff --git a/src/lib/tooltip/tooltip.ts b/src/lib/tooltip/tooltip.ts index 4b9d64428375..9e3578b79e6a 100644 --- a/src/lib/tooltip/tooltip.ts +++ b/src/lib/tooltip/tooltip.ts @@ -32,7 +32,6 @@ import { Directive, ElementRef, Inject, - inject, InjectionToken, Input, NgZone, @@ -60,17 +59,20 @@ export function getMatTooltipInvalidPositionError(position: string) { /** Injection token that determines the scroll handling while a tooltip is visible. */ export const MAT_TOOLTIP_SCROLL_STRATEGY = - new InjectionToken<() => ScrollStrategy>('mat-tooltip-scroll-strategy', { - providedIn: 'root', - factory: MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY, - }); + new InjectionToken<() => ScrollStrategy>('mat-tooltip-scroll-strategy'); /** @docs-private */ -export function MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY(): () => ScrollStrategy { - const overlay = inject(Overlay); +export function MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy { return () => overlay.scrollStrategies.reposition({scrollThrottle: SCROLL_THROTTLE_MS}); } +/** @docs-private */ +export const MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER = { + provide: MAT_TOOLTIP_SCROLL_STRATEGY, + deps: [Overlay], + useFactory: MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY, +}; + /** Default `matTooltip` options that can be overridden. */ export interface MatTooltipDefaultOptions { showDelay: number;