Skip to content

Commit d0011c4

Browse files
crisbetojelbourn
authored andcommitted
fix(overlay): ConnectedOverlayDirective not updating positions after first open (#9579)
Fixes the `ConnectedOverlayDirective` not picking up changes to the `positions` after it is opened for the first time.
1 parent b3a0de9 commit d0011c4

File tree

2 files changed

+60
-18
lines changed

2 files changed

+60
-18
lines changed

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

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import {ESCAPE} from '@angular/cdk/keycodes';
77
import {CdkConnectedOverlay, OverlayModule, CdkOverlayOrigin} from './index';
88
import {OverlayContainer} from './overlay-container';
99
import {ConnectedPositionStrategy} from './position/connected-position-strategy';
10-
import {ConnectedOverlayPositionChange} from './position/connected-position';
10+
import {
11+
ConnectedOverlayPositionChange,
12+
ConnectionPositionPair,
13+
} from './position/connected-position';
1114

1215

1316
describe('Overlay directives', () => {
@@ -268,6 +271,42 @@ describe('Overlay directives', () => {
268271
expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
269272
});
270273

274+
it('should update the positions if they change after init', () => {
275+
const trigger = fixture.nativeElement.querySelector('#trigger');
276+
277+
trigger.style.position = 'fixed';
278+
trigger.style.top = '200px';
279+
trigger.style.left = '200px';
280+
281+
fixture.componentInstance.isOpen = true;
282+
fixture.detectChanges();
283+
284+
let triggerRect = trigger.getBoundingClientRect();
285+
let overlayRect = getPaneElement().getBoundingClientRect();
286+
287+
expect(Math.floor(triggerRect.left)).toBe(Math.floor(overlayRect.left));
288+
expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
289+
290+
fixture.componentInstance.isOpen = false;
291+
fixture.detectChanges();
292+
293+
fixture.componentInstance.positionOverrides = [{
294+
originX: 'end',
295+
originY: 'bottom',
296+
overlayX: 'start',
297+
overlayY: 'top'
298+
}];
299+
300+
fixture.componentInstance.isOpen = true;
301+
fixture.detectChanges();
302+
303+
triggerRect = trigger.getBoundingClientRect();
304+
overlayRect = getPaneElement().getBoundingClientRect();
305+
306+
expect(Math.floor(triggerRect.right)).toBe(Math.floor(overlayRect.left));
307+
expect(Math.floor(triggerRect.bottom)).toBe(Math.floor(overlayRect.top));
308+
});
309+
271310
});
272311

273312
describe('outputs', () => {
@@ -328,7 +367,8 @@ describe('Overlay directives', () => {
328367
[hasBackdrop]="hasBackdrop" backdropClass="mat-test-class"
329368
(backdropClick)="backdropClicked=true" [offsetX]="offsetX" [offsetY]="offsetY"
330369
(positionChange)="positionChangeHandler($event)" (attach)="attachHandler()"
331-
(detach)="detachHandler()" [minWidth]="minWidth" [minHeight]="minHeight">
370+
(detach)="detachHandler()" [minWidth]="minWidth" [minHeight]="minHeight"
371+
[cdkConnectedOverlayPositions]="positionOverrides">
332372
<p>Menu content</p>
333373
</ng-template>`,
334374
})
@@ -348,6 +388,7 @@ class ConnectedOverlayDirectiveTest {
348388
hasBackdrop: boolean;
349389
backdropClicked = false;
350390
positionChangeHandler = jasmine.createSpy('positionChangeHandler');
391+
positionOverrides: ConnectionPositionPair[];
351392
attachHandler = jasmine.createSpy('attachHandler').and.callFake(() => {
352393
this.attachResult =
353394
this.connectedOverlayDirective.overlayRef.overlayElement.querySelector('p') as HTMLElement;

src/cdk/overlay/overlay-directives.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -292,11 +292,17 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
292292
}
293293

294294
ngOnChanges(changes: SimpleChanges) {
295-
if ((changes['origin'] || changes['_deprecatedOrigin']) && this._position) {
296-
this._position.setOrigin(this.origin.elementRef);
295+
if (this._position) {
296+
if (changes['positions'] || changes['_deprecatedPositions']) {
297+
this._position.withPositions(this.positions);
298+
}
299+
300+
if (changes['origin'] || changes['_deprecatedOrigin']) {
301+
this._position.setOrigin(this.origin.elementRef);
297302

298-
if (this.open) {
299-
this._position.apply();
303+
if (this.open) {
304+
this._position.apply();
305+
}
300306
}
301307
}
302308

@@ -348,30 +354,25 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
348354

349355
/** Returns the position strategy of the overlay to be set on the overlay config */
350356
private _createPositionStrategy(): ConnectedPositionStrategy {
351-
const pos = this.positions[0];
352-
const originPoint = {originX: pos.originX, originY: pos.originY};
353-
const overlayPoint = {overlayX: pos.overlayX, overlayY: pos.overlayY};
354-
357+
const primaryPosition = this.positions[0];
358+
const originPoint = {originX: primaryPosition.originX, originY: primaryPosition.originY};
359+
const overlayPoint = {overlayX: primaryPosition.overlayX, overlayY: primaryPosition.overlayY};
355360
const strategy = this._overlay.position()
356361
.connectedTo(this.origin.elementRef, originPoint, overlayPoint)
357362
.withOffsetX(this.offsetX)
358363
.withOffsetY(this.offsetY);
359364

360-
this._handlePositionChanges(strategy);
361-
362-
return strategy;
363-
}
364-
365-
private _handlePositionChanges(strategy: ConnectedPositionStrategy): void {
366365
for (let i = 1; i < this.positions.length; i++) {
367366
strategy.withFallbackPosition(
368367
{originX: this.positions[i].originX, originY: this.positions[i].originY},
369368
{overlayX: this.positions[i].overlayX, overlayY: this.positions[i].overlayY}
370369
);
371370
}
372371

373-
this._positionSubscription =
374-
strategy.onPositionChange.subscribe(pos => this.positionChange.emit(pos));
372+
this._positionSubscription = strategy.onPositionChange
373+
.subscribe(pos => this.positionChange.emit(pos));
374+
375+
return strategy;
375376
}
376377

377378
/** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */

0 commit comments

Comments
 (0)