diff --git a/src/cdk/overlay/overlay-directives.spec.ts b/src/cdk/overlay/overlay-directives.spec.ts
index b2bf2ed39e0..f37093350b2 100644
--- a/src/cdk/overlay/overlay-directives.spec.ts
+++ b/src/cdk/overlay/overlay-directives.spec.ts
@@ -20,11 +20,7 @@ describe('Overlay directives', () => {
TestBed.configureTestingModule({
imports: [OverlayModule],
declarations: [ConnectedOverlayDirectiveTest, ConnectedOverlayPropertyInitOrder],
- providers: [
- {provide: Directionality, useFactory: () => {
- return dir = {value: 'ltr'};
- }}
- ],
+ providers: [{provide: Directionality, useFactory: () => dir = {value: 'ltr'}}],
});
});
@@ -250,6 +246,28 @@ describe('Overlay directives', () => {
.toBe('105px', `Expected overlay directive to reflect new offsetY if it changes.`);
});
+ it('should be able to update the origin after init', () => {
+ const testComponent = fixture.componentInstance;
+
+ testComponent.isOpen = true;
+ fixture.detectChanges();
+
+ let triggerRect = fixture.nativeElement.querySelector('#trigger').getBoundingClientRect();
+ let overlayRect = getPaneElement().getBoundingClientRect();
+
+ expect(Math.floor(triggerRect.left)).toBe(Math.floor(overlayRect.left));
+ expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
+
+ testComponent.triggerOverride = testComponent.otherTrigger;
+ fixture.detectChanges();
+
+ triggerRect = fixture.nativeElement.querySelector('#otherTrigger').getBoundingClientRect();
+ overlayRect = getPaneElement().getBoundingClientRect();
+
+ expect(Math.floor(triggerRect.left)).toBe(Math.floor(overlayRect.left));
+ expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
+ });
+
});
describe('outputs', () => {
@@ -302,9 +320,11 @@ describe('Overlay directives', () => {
@Component({
template: `
-
+
+
+
{
`,
})
class ConnectedOverlayDirectiveTest {
+ @ViewChild(CdkConnectedOverlay) connectedOverlayDirective: CdkConnectedOverlay;
+ @ViewChild('trigger') trigger: CdkOverlayOrigin;
+ @ViewChild('otherTrigger') otherTrigger: CdkOverlayOrigin;
+
isOpen = false;
width: number | string;
height: number | string;
minWidth: number | string;
minHeight: number | string;
- offsetX: number = 0;
- offsetY: number = 0;
+ offsetX = 0;
+ offsetY = 0;
+ triggerOverride: CdkOverlayOrigin;
hasBackdrop: boolean;
backdropClicked = false;
positionChangeHandler = jasmine.createSpy('positionChangeHandler');
@@ -329,8 +354,6 @@ class ConnectedOverlayDirectiveTest {
});
detachHandler = jasmine.createSpy('detachHandler');
attachResult: HTMLElement;
-
- @ViewChild(CdkConnectedOverlay) connectedOverlayDirective: CdkConnectedOverlay;
}
@Component({
diff --git a/src/cdk/overlay/overlay-directives.ts b/src/cdk/overlay/overlay-directives.ts
index 35cbfdb1190..54dc66465dc 100644
--- a/src/cdk/overlay/overlay-directives.ts
+++ b/src/cdk/overlay/overlay-directives.ts
@@ -256,6 +256,14 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
}
ngOnChanges(changes: SimpleChanges) {
+ if ((changes['origin'] || changes['_deprecatedOrigin']) && this._position) {
+ this._position.setOrigin(this.origin.elementRef);
+
+ if (this.open) {
+ this._position.apply();
+ }
+ }
+
if (changes['open'] || changes['_deprecatedOpen']) {
this.open ? this._attachOverlay() : this._detachOverlay();
}
diff --git a/src/cdk/overlay/position/connected-position-strategy.ts b/src/cdk/overlay/position/connected-position-strategy.ts
index 6dd2d337e12..ad8561e1742 100644
--- a/src/cdk/overlay/position/connected-position-strategy.ts
+++ b/src/cdk/overlay/position/connected-position-strategy.ts
@@ -265,6 +265,15 @@ export class ConnectedPositionStrategy implements PositionStrategy {
return this;
}
+ /**
+ * Sets the origin element, relative to which to position the overlay.
+ * @param origin Reference to the new origin element.
+ */
+ setOrigin(origin: ElementRef): this {
+ this._origin = origin.nativeElement;
+ return this;
+ }
+
/**
* Gets the horizontal (x) "start" dimension based on whether the overlay is in an RTL context.
* @param rect