Skip to content

Commit 8d00344

Browse files
committed
fix(cdk/overlay): simplify public API of overlay directive
Currently the `CdkConnectedOverlay` directive has 23 inputs which can be quite verbose. These changes add a shorthand through the `cdkConnectedOverlay` attribute for the cases where these values aren't expected to change. (cherry picked from commit fab9dd3)
1 parent 47bdfb2 commit 8d00344

File tree

3 files changed

+129
-19
lines changed

3 files changed

+129
-19
lines changed

goldens/cdk/overlay/index.api.md

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
4444
attachOverlay(): void;
4545
backdropClass: string | string[];
4646
readonly backdropClick: EventEmitter<MouseEvent>;
47+
set _config(value: string | CdkConnectedOverlayConfig);
4748
readonly detach: EventEmitter<void>;
4849
detachOverlay(): void;
4950
get dir(): Direction;
5051
disableClose: boolean;
51-
get disposeOnNavigation(): boolean;
52-
set disposeOnNavigation(value: boolean);
52+
disposeOnNavigation: boolean;
5353
flexibleDimensions: boolean;
5454
growAfterOpen: boolean;
5555
hasBackdrop: boolean;
@@ -95,11 +95,61 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
9595
viewportMargin: ViewportMargin;
9696
width: number | string;
9797
// (undocumented)
98-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkConnectedOverlay, "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", ["cdkConnectedOverlay"], { "origin": { "alias": "cdkConnectedOverlayOrigin"; "required": false; }; "positions": { "alias": "cdkConnectedOverlayPositions"; "required": false; }; "positionStrategy": { "alias": "cdkConnectedOverlayPositionStrategy"; "required": false; }; "offsetX": { "alias": "cdkConnectedOverlayOffsetX"; "required": false; }; "offsetY": { "alias": "cdkConnectedOverlayOffsetY"; "required": false; }; "width": { "alias": "cdkConnectedOverlayWidth"; "required": false; }; "height": { "alias": "cdkConnectedOverlayHeight"; "required": false; }; "minWidth": { "alias": "cdkConnectedOverlayMinWidth"; "required": false; }; "minHeight": { "alias": "cdkConnectedOverlayMinHeight"; "required": false; }; "backdropClass": { "alias": "cdkConnectedOverlayBackdropClass"; "required": false; }; "panelClass": { "alias": "cdkConnectedOverlayPanelClass"; "required": false; }; "viewportMargin": { "alias": "cdkConnectedOverlayViewportMargin"; "required": false; }; "scrollStrategy": { "alias": "cdkConnectedOverlayScrollStrategy"; "required": false; }; "open": { "alias": "cdkConnectedOverlayOpen"; "required": false; }; "disableClose": { "alias": "cdkConnectedOverlayDisableClose"; "required": false; }; "transformOriginSelector": { "alias": "cdkConnectedOverlayTransformOriginOn"; "required": false; }; "hasBackdrop": { "alias": "cdkConnectedOverlayHasBackdrop"; "required": false; }; "lockPosition": { "alias": "cdkConnectedOverlayLockPosition"; "required": false; }; "flexibleDimensions": { "alias": "cdkConnectedOverlayFlexibleDimensions"; "required": false; }; "growAfterOpen": { "alias": "cdkConnectedOverlayGrowAfterOpen"; "required": false; }; "push": { "alias": "cdkConnectedOverlayPush"; "required": false; }; "disposeOnNavigation": { "alias": "cdkConnectedOverlayDisposeOnNavigation"; "required": false; }; "usePopover": { "alias": "cdkConnectedOverlayUsePopover"; "required": false; }; }, { "backdropClick": "backdropClick"; "positionChange": "positionChange"; "attach": "attach"; "detach": "detach"; "overlayKeydown": "overlayKeydown"; "overlayOutsideClick": "overlayOutsideClick"; }, never, never, true, never>;
98+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkConnectedOverlay, "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", ["cdkConnectedOverlay"], { "origin": { "alias": "cdkConnectedOverlayOrigin"; "required": false; }; "positions": { "alias": "cdkConnectedOverlayPositions"; "required": false; }; "positionStrategy": { "alias": "cdkConnectedOverlayPositionStrategy"; "required": false; }; "offsetX": { "alias": "cdkConnectedOverlayOffsetX"; "required": false; }; "offsetY": { "alias": "cdkConnectedOverlayOffsetY"; "required": false; }; "width": { "alias": "cdkConnectedOverlayWidth"; "required": false; }; "height": { "alias": "cdkConnectedOverlayHeight"; "required": false; }; "minWidth": { "alias": "cdkConnectedOverlayMinWidth"; "required": false; }; "minHeight": { "alias": "cdkConnectedOverlayMinHeight"; "required": false; }; "backdropClass": { "alias": "cdkConnectedOverlayBackdropClass"; "required": false; }; "panelClass": { "alias": "cdkConnectedOverlayPanelClass"; "required": false; }; "viewportMargin": { "alias": "cdkConnectedOverlayViewportMargin"; "required": false; }; "scrollStrategy": { "alias": "cdkConnectedOverlayScrollStrategy"; "required": false; }; "open": { "alias": "cdkConnectedOverlayOpen"; "required": false; }; "disableClose": { "alias": "cdkConnectedOverlayDisableClose"; "required": false; }; "transformOriginSelector": { "alias": "cdkConnectedOverlayTransformOriginOn"; "required": false; }; "hasBackdrop": { "alias": "cdkConnectedOverlayHasBackdrop"; "required": false; }; "lockPosition": { "alias": "cdkConnectedOverlayLockPosition"; "required": false; }; "flexibleDimensions": { "alias": "cdkConnectedOverlayFlexibleDimensions"; "required": false; }; "growAfterOpen": { "alias": "cdkConnectedOverlayGrowAfterOpen"; "required": false; }; "push": { "alias": "cdkConnectedOverlayPush"; "required": false; }; "disposeOnNavigation": { "alias": "cdkConnectedOverlayDisposeOnNavigation"; "required": false; }; "usePopover": { "alias": "cdkConnectedOverlayUsePopover"; "required": false; }; "_config": { "alias": "cdkConnectedOverlay"; "required": false; }; }, { "backdropClick": "backdropClick"; "positionChange": "positionChange"; "attach": "attach"; "detach": "detach"; "overlayKeydown": "overlayKeydown"; "overlayOutsideClick": "overlayOutsideClick"; }, never, never, true, never>;
9999
// (undocumented)
100100
static ɵfac: i0.ɵɵFactoryDeclaration<CdkConnectedOverlay, never>;
101101
}
102102

103+
// @public
104+
export interface CdkConnectedOverlayConfig {
105+
// (undocumented)
106+
backdropClass?: string | string[];
107+
// (undocumented)
108+
disableClose?: boolean;
109+
// (undocumented)
110+
disposeOnNavigation?: boolean;
111+
// (undocumented)
112+
flexibleDimensions?: boolean;
113+
// (undocumented)
114+
growAfterOpen?: boolean;
115+
// (undocumented)
116+
hasBackdrop?: boolean;
117+
// (undocumented)
118+
height?: number | string;
119+
// (undocumented)
120+
lockPosition?: boolean;
121+
// (undocumented)
122+
matchWidth?: boolean;
123+
// (undocumented)
124+
minHeight?: number | string;
125+
// (undocumented)
126+
minWidth?: number | string;
127+
// (undocumented)
128+
offsetX?: number;
129+
// (undocumented)
130+
offsetY?: number;
131+
// (undocumented)
132+
origin?: CdkOverlayOrigin | FlexibleConnectedPositionStrategyOrigin;
133+
// (undocumented)
134+
panelClass?: string | string[];
135+
// (undocumented)
136+
positions?: ConnectedPosition[];
137+
// (undocumented)
138+
positionStrategy?: FlexibleConnectedPositionStrategy;
139+
// (undocumented)
140+
push?: boolean;
141+
// (undocumented)
142+
scrollStrategy?: ScrollStrategy;
143+
// (undocumented)
144+
transformOriginSelector?: string;
145+
// (undocumented)
146+
usePopover?: boolean;
147+
// (undocumented)
148+
viewportMargin?: ViewportMargin;
149+
// (undocumented)
150+
width?: number | string;
151+
}
152+
103153
// @public
104154
export class CdkOverlayOrigin {
105155
constructor(...args: unknown[]);

src/cdk/overlay/overlay-directives.ts

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,33 @@ export class CdkOverlayOrigin {
9696
constructor() {}
9797
}
9898

99+
/** Object used to configure the `CdkConnectedOverlay` directive. */
100+
export interface CdkConnectedOverlayConfig {
101+
origin?: CdkOverlayOrigin | FlexibleConnectedPositionStrategyOrigin;
102+
positions?: ConnectedPosition[];
103+
positionStrategy?: FlexibleConnectedPositionStrategy;
104+
offsetX?: number;
105+
offsetY?: number;
106+
width?: number | string;
107+
height?: number | string;
108+
minWidth?: number | string;
109+
minHeight?: number | string;
110+
backdropClass?: string | string[];
111+
panelClass?: string | string[];
112+
viewportMargin?: ViewportMargin;
113+
scrollStrategy?: ScrollStrategy;
114+
disableClose?: boolean;
115+
transformOriginSelector?: string;
116+
hasBackdrop?: boolean;
117+
lockPosition?: boolean;
118+
flexibleDimensions?: boolean;
119+
growAfterOpen?: boolean;
120+
push?: boolean;
121+
disposeOnNavigation?: boolean;
122+
usePopover?: boolean;
123+
matchWidth?: boolean;
124+
}
125+
99126
/**
100127
* Directive to facilitate declarative creation of an
101128
* Overlay using a FlexibleConnectedPositionStrategy.
@@ -118,7 +145,6 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
118145
private _offsetY: number;
119146
private _position: FlexibleConnectedPositionStrategy;
120147
private _scrollStrategyFactory = inject(CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY);
121-
private _disposeOnNavigation = false;
122148
private _ngZone = inject(NgZone);
123149

124150
/** Origin for the connected overlay. */
@@ -214,17 +240,20 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
214240

215241
/** Whether the overlay should be disposed of when the user goes backwards/forwards in history. */
216242
@Input({alias: 'cdkConnectedOverlayDisposeOnNavigation', transform: booleanAttribute})
217-
get disposeOnNavigation(): boolean {
218-
return this._disposeOnNavigation;
219-
}
220-
set disposeOnNavigation(value: boolean) {
221-
this._disposeOnNavigation = value;
222-
}
243+
disposeOnNavigation: boolean = false;
223244

224245
/** Whether the connected overlay should be rendered inside a popover element or the overlay container. */
225246
@Input({alias: 'cdkConnectedOverlayUsePopover', transform: booleanAttribute})
226247
usePopover: boolean = false;
227248

249+
/** Shorthand for setting multiple overlay options at once. */
250+
@Input('cdkConnectedOverlay')
251+
set _config(value: string | CdkConnectedOverlayConfig) {
252+
if (typeof value !== 'string') {
253+
this._assignConfig(value);
254+
}
255+
}
256+
228257
/** Event emitted when the backdrop is clicked. */
229258
@Output() readonly backdropClick = new EventEmitter<MouseEvent>();
230259

@@ -419,19 +448,21 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
419448
attachOverlay() {
420449
if (!this._overlayRef) {
421450
this._createOverlay();
422-
} else {
423-
// Update the overlay size, in case the directive's inputs have changed
424-
this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop;
425451
}
426452

427-
if (!this._overlayRef!.hasAttached()) {
428-
this._overlayRef!.attach(this._templatePortal);
453+
const ref = this._overlayRef!;
454+
455+
// Update the overlay size, in case the directive's inputs have changed
456+
ref.getConfig().hasBackdrop = this.hasBackdrop;
457+
458+
if (!ref.hasAttached()) {
459+
ref.attach(this._templatePortal);
429460
}
430461

431462
if (this.hasBackdrop) {
432-
this._backdropSubscription = this._overlayRef!.backdropClick().subscribe(event => {
433-
this.backdropClick.emit(event);
434-
});
463+
this._backdropSubscription = ref
464+
.backdropClick()
465+
.subscribe(event => this.backdropClick.emit(event));
435466
} else {
436467
this._backdropSubscription.unsubscribe();
437468
}
@@ -462,4 +493,29 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
462493
this._positionSubscription.unsubscribe();
463494
this.open = false;
464495
}
496+
497+
private _assignConfig(config: CdkConnectedOverlayConfig) {
498+
this.origin = config.origin ?? this.origin;
499+
this.positions = config.positions ?? this.positions;
500+
this.positionStrategy = config.positionStrategy ?? this.positionStrategy;
501+
this.offsetX = config.offsetX ?? this.offsetX;
502+
this.offsetY = config.offsetY ?? this.offsetY;
503+
this.width = config.width ?? this.width;
504+
this.height = config.height ?? this.height;
505+
this.minWidth = config.minWidth ?? this.minWidth;
506+
this.minHeight = config.minHeight ?? this.minHeight;
507+
this.backdropClass = config.backdropClass ?? this.backdropClass;
508+
this.panelClass = config.panelClass ?? this.panelClass;
509+
this.viewportMargin = config.viewportMargin ?? this.viewportMargin;
510+
this.scrollStrategy = config.scrollStrategy ?? this.scrollStrategy;
511+
this.disableClose = config.disableClose ?? this.disableClose;
512+
this.transformOriginSelector = config.transformOriginSelector ?? this.transformOriginSelector;
513+
this.hasBackdrop = config.hasBackdrop ?? this.hasBackdrop;
514+
this.lockPosition = config.lockPosition ?? this.lockPosition;
515+
this.flexibleDimensions = config.flexibleDimensions ?? this.flexibleDimensions;
516+
this.growAfterOpen = config.growAfterOpen ?? this.growAfterOpen;
517+
this.push = config.push ?? this.push;
518+
this.disposeOnNavigation = config.disposeOnNavigation ?? this.disposeOnNavigation;
519+
this.usePopover = config.usePopover ?? this.usePopover;
520+
}
465521
}

src/cdk/overlay/public-api.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ export * from './overlay-module';
1313
export * from './dispatchers/index';
1414
export {Overlay, createOverlayRef} from './overlay';
1515
export {OverlayContainer} from './overlay-container';
16-
export {CdkOverlayOrigin, CdkConnectedOverlay} from './overlay-directives';
16+
export {
17+
CdkOverlayOrigin,
18+
CdkConnectedOverlay,
19+
CdkConnectedOverlayConfig,
20+
} from './overlay-directives';
1721
export {FullscreenOverlayContainer} from './fullscreen-overlay-container';
1822
export {OverlayRef, OverlaySizeConfig} from './overlay-ref';
1923
export {ViewportRuler} from '../scrolling';

0 commit comments

Comments
 (0)