Skip to content

Commit 02dfcc6

Browse files
committed
feat(cdk/overlay): Extend cdkConnectedOverlayOrigin to support more types.
`CdkConnectedOverlay` directive's input `cdkConnectedOverlayOrigin` only supports `CdkOverlayOrigin`. `FlexibleConnectedPositionStrategy` supports a lot more types. Add support for them. Fixes #23252
1 parent 56a30d0 commit 02dfcc6

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

src/cdk/overlay/overlay-directives.spec.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, ViewChild} from '@angular/core';
1+
import {Component, ElementRef, ViewChild} from '@angular/core';
22
import {By} from '@angular/platform-browser';
33
import {
44
ComponentFixture,
@@ -28,7 +28,10 @@ import {
2828
ConnectedOverlayPositionChange,
2929
ConnectionPositionPair,
3030
} from './position/connected-position';
31-
import {FlexibleConnectedPositionStrategy} from './position/flexible-connected-position-strategy';
31+
import {
32+
FlexibleConnectedPositionStrategy,
33+
FlexibleConnectedPositionStrategyOrigin,
34+
} from './position/flexible-connected-position-strategy';
3235
import {Subject} from 'rxjs';
3336

3437

@@ -408,6 +411,21 @@ describe('Overlay directives', () => {
408411
expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
409412
});
410413

414+
it('should be able to use non-directive origin', () => {
415+
const testComponent = fixture.componentInstance;
416+
417+
testComponent.triggerOverride = testComponent.nonDirectiveTrigger;
418+
testComponent.isOpen = true;
419+
fixture.detectChanges();
420+
421+
const triggerRect =
422+
fixture.nativeElement.querySelector('#nonDirectiveTrigger').getBoundingClientRect();
423+
const overlayRect = getPaneElement().getBoundingClientRect();
424+
425+
expect(Math.floor(triggerRect.left)).toBe(Math.floor(overlayRect.left));
426+
expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
427+
});
428+
411429
it('should update the positions if they change after init', () => {
412430
const trigger = fixture.nativeElement.querySelector('#trigger');
413431

@@ -674,6 +692,7 @@ describe('Overlay directives', () => {
674692
template: `
675693
<button cdk-overlay-origin id="trigger" #trigger="cdkOverlayOrigin">Toggle menu</button>
676694
<button cdk-overlay-origin id="otherTrigger" #otherTrigger="cdkOverlayOrigin">Toggle menu</button>
695+
<button id="nonDirectiveTrigger" #nonDirectiveTrigger>Toggle menu</button>
677696
678697
<ng-template cdk-connected-overlay
679698
[cdkConnectedOverlayOpen]="isOpen"
@@ -708,6 +727,7 @@ class ConnectedOverlayDirectiveTest {
708727
@ViewChild(CdkConnectedOverlay) connectedOverlayDirective: CdkConnectedOverlay;
709728
@ViewChild('trigger') trigger: CdkOverlayOrigin;
710729
@ViewChild('otherTrigger') otherTrigger: CdkOverlayOrigin;
730+
@ViewChild('nonDirectiveTrigger') nonDirectiveTrigger: ElementRef<HTMLElement>;
711731

712732
isOpen = false;
713733
width: number | string;
@@ -717,7 +737,7 @@ class ConnectedOverlayDirectiveTest {
717737
minHeight: number | string;
718738
offsetX: number;
719739
offsetY: number;
720-
triggerOverride: CdkOverlayOrigin;
740+
triggerOverride: CdkOverlayOrigin|FlexibleConnectedPositionStrategyOrigin;
721741
hasBackdrop: boolean;
722742
disableClose: boolean;
723743
viewportMargin: number;

src/cdk/overlay/overlay-directives.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {ConnectedOverlayPositionChange} from './position/connected-position';
3434
import {
3535
ConnectedPosition,
3636
FlexibleConnectedPositionStrategy,
37+
FlexibleConnectedPositionStrategyOrigin,
3738
} from './position/flexible-connected-position-strategy';
3839
import {
3940
RepositionScrollStrategy,
@@ -114,7 +115,8 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
114115
private _scrollStrategyFactory: () => ScrollStrategy;
115116

116117
/** Origin for the connected overlay. */
117-
@Input('cdkConnectedOverlayOrigin') origin: CdkOverlayOrigin;
118+
@Input('cdkConnectedOverlayOrigin')
119+
origin: CdkOverlayOrigin|FlexibleConnectedPositionStrategyOrigin;
118120

119121
/** Registered connected position pairs. */
120122
@Input('cdkConnectedOverlayPositions') positions: ConnectedPosition[];
@@ -352,24 +354,32 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
352354
panelClass: currentPosition.panelClass || undefined,
353355
}));
354356

355-
return positionStrategy
356-
.setOrigin(this.origin.elementRef)
357-
.withPositions(positions)
358-
.withFlexibleDimensions(this.flexibleDimensions)
359-
.withPush(this.push)
360-
.withGrowAfterOpen(this.growAfterOpen)
361-
.withViewportMargin(this.viewportMargin)
362-
.withLockedPosition(this.lockPosition)
363-
.withTransformOriginOn(this.transformOriginSelector);
357+
return positionStrategy.setOrigin(this._getFlexibleConnectedPositionStrategyOrigin())
358+
.withPositions(positions)
359+
.withFlexibleDimensions(this.flexibleDimensions)
360+
.withPush(this.push)
361+
.withGrowAfterOpen(this.growAfterOpen)
362+
.withViewportMargin(this.viewportMargin)
363+
.withLockedPosition(this.lockPosition)
364+
.withTransformOriginOn(this.transformOriginSelector);
364365
}
365366

366367
/** Returns the position strategy of the overlay to be set on the overlay config */
367368
private _createPositionStrategy(): FlexibleConnectedPositionStrategy {
368-
const strategy = this._overlay.position().flexibleConnectedTo(this.origin.elementRef);
369+
const strategy = this._overlay.position().flexibleConnectedTo(
370+
this._getFlexibleConnectedPositionStrategyOrigin());
369371
this._updatePositionStrategy(strategy);
370372
return strategy;
371373
}
372374

375+
private _getFlexibleConnectedPositionStrategyOrigin(): FlexibleConnectedPositionStrategyOrigin {
376+
if (this.origin instanceof CdkOverlayOrigin) {
377+
return this.origin.elementRef;
378+
} else {
379+
return this.origin;
380+
}
381+
}
382+
373383
/** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */
374384
private _attachOverlay() {
375385
if (!this._overlayRef) {

0 commit comments

Comments
 (0)