Skip to content

Commit 0db3635

Browse files
jelbournkara
authored andcommitted
chore(overlay): add attach method to PositionStrategy interface (#6505)
1 parent 215ff3c commit 0db3635

7 files changed

+122
-67
lines changed

src/cdk/overlay/overlay-ref.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export class OverlayRef implements PortalHost {
4545
attach(portal: Portal<any>): any {
4646
let attachResult = this._portalHost.attach(portal);
4747

48+
if (this._state.positionStrategy) {
49+
this._state.positionStrategy.attach(this);
50+
}
51+
4852
// Update the pane element with the given state configuration.
4953
this._updateStackingOrder();
5054
this.updateSize();
@@ -146,7 +150,7 @@ export class OverlayRef implements PortalHost {
146150
/** Updates the position of the overlay based on the position strategy. */
147151
updatePosition() {
148152
if (this._state.positionStrategy) {
149-
this._state.positionStrategy.apply(this._pane);
153+
this._state.positionStrategy.apply();
150154
}
151155
}
152156

src/cdk/overlay/overlay.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,14 @@ class OverlayTestModule { }
532532
class OverlayContainerThemingTestModule { }
533533

534534
class FakePositionStrategy implements PositionStrategy {
535-
apply(element: Element): Promise<null> {
536-
element.classList.add('fake-positioned');
537-
return Promise.resolve(null);
535+
element: HTMLElement;
536+
537+
apply(): void {
538+
this.element.classList.add('fake-positioned');
539+
}
540+
541+
attach(overlayRef: OverlayRef) {
542+
this.element = overlayRef.overlayElement;
538543
}
539544

540545
dispose() {}

src/cdk/overlay/position/connected-position-strategy.spec.ts

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {ConnectedOverlayPositionChange} from './connected-position';
77
import {Scrollable} from '../scroll/scrollable';
88
import {Subscription} from 'rxjs/Subscription';
99
import {ScrollDispatchModule} from '../scroll/index';
10+
import {OverlayRef} from '../overlay-ref';
1011

1112

1213
// Default width and height of the overlay and origin panels throughout these tests.
@@ -142,7 +143,8 @@ describe('ConnectedPositionStrategy', () => {
142143
{originX: 'start', originY: 'bottom'},
143144
{overlayX: 'start', overlayY: 'top'});
144145

145-
strategy.apply(overlayElement);
146+
strategy.attach(fakeOverlayRef(overlayElement));
147+
strategy.apply();
146148

147149
let overlayRect = overlayElement.getBoundingClientRect();
148150
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.bottom));
@@ -166,7 +168,8 @@ describe('ConnectedPositionStrategy', () => {
166168
{originX: 'end', originY: 'center'},
167169
{overlayX: 'start', overlayY: 'center'});
168170

169-
strategy.apply(overlayElement);
171+
strategy.attach(fakeOverlayRef(overlayElement));
172+
strategy.apply();
170173

171174
let overlayRect = overlayElement.getBoundingClientRect();
172175
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originCenterY - (OVERLAY_HEIGHT / 2)));
@@ -188,7 +191,8 @@ describe('ConnectedPositionStrategy', () => {
188191
{originX: 'end', originY: 'top'},
189192
{overlayX: 'end', overlayY: 'bottom'});
190193

191-
strategy.apply(overlayElement);
194+
strategy.attach(fakeOverlayRef(overlayElement));
195+
strategy.apply();
192196

193197
let overlayRect = overlayElement.getBoundingClientRect();
194198
expect(Math.floor(overlayRect.bottom)).toBe(Math.floor(originRect.top));
@@ -210,7 +214,8 @@ describe('ConnectedPositionStrategy', () => {
210214
{originX: 'start', originY: 'bottom'},
211215
{overlayX: 'end', overlayY: 'top'});
212216

213-
strategy.apply(overlayElement);
217+
strategy.attach(fakeOverlayRef(overlayElement));
218+
strategy.apply();
214219

215220
let overlayRect = overlayElement.getBoundingClientRect();
216221

@@ -234,7 +239,8 @@ describe('ConnectedPositionStrategy', () => {
234239
{overlayX: 'start', overlayY: 'bottom'});
235240

236241
// This should apply the fallback position, as the original position won't fit.
237-
strategy.apply(overlayElement);
242+
strategy.attach(fakeOverlayRef(overlayElement));
243+
strategy.apply();
238244

239245
// Now make the overlay small enough to fit in the first preferred position.
240246
overlayElement.style.height = '15px';
@@ -260,7 +266,8 @@ describe('ConnectedPositionStrategy', () => {
260266
{originX: 'start', originY: 'top'},
261267
{overlayX: 'start', overlayY: 'bottom'});
262268

263-
strategy.apply(overlayElement);
269+
strategy.attach(fakeOverlayRef(overlayElement));
270+
strategy.apply();
264271
strategy.recalculateLastPosition();
265272

266273
let overlayRect = overlayElement.getBoundingClientRect();
@@ -279,7 +286,8 @@ describe('ConnectedPositionStrategy', () => {
279286
{overlayX: 'start', overlayY: 'top'})
280287
.withDirection('rtl');
281288

282-
strategy.apply(overlayElement);
289+
strategy.attach(fakeOverlayRef(overlayElement));
290+
strategy.apply();
283291

284292
let overlayRect = overlayElement.getBoundingClientRect();
285293
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.bottom));
@@ -294,7 +302,8 @@ describe('ConnectedPositionStrategy', () => {
294302
{overlayX: 'start', overlayY: 'top'});
295303

296304
strategy.withOffsetX(10);
297-
strategy.apply(overlayElement);
305+
strategy.attach(fakeOverlayRef(overlayElement));
306+
strategy.apply();
298307

299308
let overlayRect = overlayElement.getBoundingClientRect();
300309
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top));
@@ -309,7 +318,8 @@ describe('ConnectedPositionStrategy', () => {
309318
{overlayX: 'start', overlayY: 'top'});
310319

311320
strategy.withOffsetY(50);
312-
strategy.apply(overlayElement);
321+
strategy.attach(fakeOverlayRef(overlayElement));
322+
strategy.apply();
313323

314324
let overlayRect = overlayElement.getBoundingClientRect();
315325
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top + 50));
@@ -334,7 +344,8 @@ describe('ConnectedPositionStrategy', () => {
334344
const positionChangeHandler = jasmine.createSpy('positionChangeHandler');
335345
const subscription = strategy.onPositionChange.subscribe(positionChangeHandler);
336346

337-
strategy.apply(overlayElement);
347+
strategy.attach(fakeOverlayRef(overlayElement));
348+
strategy.apply();
338349

339350
const latestCall = positionChangeHandler.calls.mostRecent();
340351

@@ -346,7 +357,8 @@ describe('ConnectedPositionStrategy', () => {
346357
// the position change event should be emitted again.
347358
originElement.style.top = '200px';
348359
originElement.style.left = '200px';
349-
strategy.apply(overlayElement);
360+
strategy.attach(fakeOverlayRef(overlayElement));
361+
strategy.apply();
350362

351363
expect(positionChangeHandler).toHaveBeenCalledTimes(2);
352364

@@ -369,7 +381,8 @@ describe('ConnectedPositionStrategy', () => {
369381
const positionChangeHandler = jasmine.createSpy('positionChangeHandler');
370382
const subscription = strategy.onPositionChange.subscribe(positionChangeHandler);
371383

372-
strategy.apply(overlayElement);
384+
strategy.attach(fakeOverlayRef(overlayElement));
385+
strategy.apply();
373386

374387
expect(positionChangeHandler).toHaveBeenCalled();
375388

@@ -394,7 +407,8 @@ describe('ConnectedPositionStrategy', () => {
394407
{originX: 'end', originY: 'top'},
395408
{overlayX: 'end', overlayY: 'top'});
396409

397-
strategy.apply(overlayElement);
410+
strategy.attach(fakeOverlayRef(overlayElement));
411+
strategy.apply();
398412

399413
let overlayRect = overlayElement.getBoundingClientRect();
400414

@@ -415,7 +429,8 @@ describe('ConnectedPositionStrategy', () => {
415429
{originX: 'start', originY: 'bottom'},
416430
{overlayX: 'start', overlayY: 'top'});
417431

418-
strategy.apply(overlayElement);
432+
strategy.attach(fakeOverlayRef(overlayElement));
433+
strategy.apply();
419434

420435
let overlayRect = overlayElement.getBoundingClientRect();
421436
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect!.bottom));
@@ -428,7 +443,8 @@ describe('ConnectedPositionStrategy', () => {
428443
{originX: 'end', originY: 'center'},
429444
{overlayX: 'start', overlayY: 'center'});
430445

431-
strategy.apply(overlayElement);
446+
strategy.attach(fakeOverlayRef(overlayElement));
447+
strategy.apply();
432448

433449
let overlayRect = overlayElement.getBoundingClientRect();
434450
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originCenterY! - (OVERLAY_HEIGHT / 2)));
@@ -441,7 +457,8 @@ describe('ConnectedPositionStrategy', () => {
441457
{originX: 'start', originY: 'bottom'},
442458
{overlayX: 'end', overlayY: 'top'});
443459

444-
strategy.apply(overlayElement);
460+
strategy.attach(fakeOverlayRef(overlayElement));
461+
strategy.apply();
445462

446463
let overlayRect = overlayElement.getBoundingClientRect();
447464

@@ -455,7 +472,8 @@ describe('ConnectedPositionStrategy', () => {
455472
{originX: 'end', originY: 'top'},
456473
{overlayX: 'end', overlayY: 'bottom'});
457474

458-
strategy.apply(overlayElement);
475+
strategy.attach(fakeOverlayRef(overlayElement));
476+
strategy.apply();
459477

460478
let overlayRect = overlayElement.getBoundingClientRect();
461479
expect(Math.round(overlayRect.bottom)).toBe(Math.round(originRect!.top));
@@ -468,7 +486,8 @@ describe('ConnectedPositionStrategy', () => {
468486
{originX: 'center', originY: 'bottom'},
469487
{overlayX: 'center', overlayY: 'top'});
470488

471-
strategy.apply(overlayElement);
489+
strategy.attach(fakeOverlayRef(overlayElement));
490+
strategy.apply();
472491

473492
let overlayRect = overlayElement.getBoundingClientRect();
474493
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect!.bottom));
@@ -481,7 +500,8 @@ describe('ConnectedPositionStrategy', () => {
481500
{originX: 'center', originY: 'center'},
482501
{overlayX: 'center', overlayY: 'center'});
483502

484-
strategy.apply(overlayElement);
503+
strategy.attach(fakeOverlayRef(overlayElement));
504+
strategy.apply();
485505

486506
let overlayRect = overlayElement.getBoundingClientRect();
487507
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect!.top));
@@ -526,7 +546,7 @@ describe('ConnectedPositionStrategy', () => {
526546

527547
strategy.withScrollableContainers([
528548
new Scrollable(new FakeElementRef(scrollable), null!, null!, null!)]);
529-
549+
strategy.attach(fakeOverlayRef(overlayElement));
530550
positionChangeHandler = jasmine.createSpy('positionChangeHandler');
531551
onPositionChangeSubscription = strategy.onPositionChange.subscribe(positionChangeHandler);
532552
});
@@ -538,7 +558,7 @@ describe('ConnectedPositionStrategy', () => {
538558
});
539559

540560
it('should not have origin or overlay clipped or out of view without scroll', () => {
541-
strategy.apply(overlayElement);
561+
strategy.apply();
542562

543563
expect(positionChangeHandler).toHaveBeenCalled();
544564
positionChange = positionChangeHandler.calls.mostRecent().args[0];
@@ -552,7 +572,7 @@ describe('ConnectedPositionStrategy', () => {
552572

553573
it('should evaluate if origin is clipped if scrolled slightly down', () => {
554574
scrollable.scrollTop = 10; // Clip the origin by 10 pixels
555-
strategy.apply(overlayElement);
575+
strategy.apply();
556576

557577
expect(positionChangeHandler).toHaveBeenCalled();
558578
positionChange = positionChangeHandler.calls.mostRecent().args[0];
@@ -566,7 +586,7 @@ describe('ConnectedPositionStrategy', () => {
566586

567587
it('should evaluate if origin is out of view and overlay is clipped if scrolled enough', () => {
568588
scrollable.scrollTop = 31; // Origin is 30 pixels, move out of view and clip the overlay 1px
569-
strategy.apply(overlayElement);
589+
strategy.apply();
570590

571591
expect(positionChangeHandler).toHaveBeenCalled();
572592
positionChange = positionChangeHandler.calls.mostRecent().args[0];
@@ -580,7 +600,7 @@ describe('ConnectedPositionStrategy', () => {
580600

581601
it('should evaluate the overlay and origin are both out of the view', () => {
582602
scrollable.scrollTop = 61; // Scroll by overlay height + origin height + 1px buffer
583-
strategy.apply(overlayElement);
603+
strategy.apply();
584604

585605
expect(positionChangeHandler).toHaveBeenCalled();
586606
positionChange = positionChangeHandler.calls.mostRecent().args[0];
@@ -626,7 +646,8 @@ describe('ConnectedPositionStrategy', () => {
626646
{originX: 'start', originY: 'top'},
627647
{overlayX: 'start', overlayY: 'top'});
628648

629-
strategy.apply(overlayElement);
649+
strategy.attach(fakeOverlayRef(overlayElement));
650+
strategy.apply();
630651
expect(overlayElement.style.left).toBeTruthy();
631652
expect(overlayElement.style.right).toBeFalsy();
632653
});
@@ -637,7 +658,8 @@ describe('ConnectedPositionStrategy', () => {
637658
{originX: 'end', originY: 'top'},
638659
{overlayX: 'end', overlayY: 'top'});
639660

640-
strategy.apply(overlayElement);
661+
strategy.attach(fakeOverlayRef(overlayElement));
662+
strategy.apply();
641663
expect(overlayElement.style.right).toBeTruthy();
642664
expect(overlayElement.style.left).toBeFalsy();
643665
});
@@ -653,7 +675,8 @@ describe('ConnectedPositionStrategy', () => {
653675
)
654676
.withDirection('rtl');
655677

656-
strategy.apply(overlayElement);
678+
strategy.attach(fakeOverlayRef(overlayElement));
679+
strategy.apply();
657680
expect(overlayElement.style.right).toBeTruthy();
658681
expect(overlayElement.style.left).toBeFalsy();
659682
});
@@ -665,7 +688,8 @@ describe('ConnectedPositionStrategy', () => {
665688
{overlayX: 'end', overlayY: 'top'}
666689
).withDirection('rtl');
667690

668-
strategy.apply(overlayElement);
691+
strategy.attach(fakeOverlayRef(overlayElement));
692+
strategy.apply();
669693
expect(overlayElement.style.left).toBeTruthy();
670694
expect(overlayElement.style.right).toBeFalsy();
671695
});
@@ -679,7 +703,8 @@ describe('ConnectedPositionStrategy', () => {
679703
{overlayX: 'start', overlayY: 'top'}
680704
);
681705

682-
strategy.apply(overlayElement);
706+
strategy.attach(fakeOverlayRef(overlayElement));
707+
strategy.apply();
683708
expect(overlayElement.style.top).toBeTruthy();
684709
expect(overlayElement.style.bottom).toBeFalsy();
685710
});
@@ -691,7 +716,8 @@ describe('ConnectedPositionStrategy', () => {
691716
{overlayX: 'start', overlayY: 'bottom'}
692717
);
693718

694-
strategy.apply(overlayElement);
719+
strategy.attach(fakeOverlayRef(overlayElement));
720+
strategy.apply();
695721
expect(overlayElement.style.bottom).toBeTruthy();
696722
expect(overlayElement.style.top).toBeFalsy();
697723
});
@@ -741,3 +767,7 @@ function createOverflowContainerElement() {
741767
class FakeElementRef implements ElementRef {
742768
constructor(public nativeElement: HTMLElement) { }
743769
}
770+
771+
function fakeOverlayRef(overlayElement: HTMLElement) {
772+
return {overlayElement} as OverlayRef;
773+
}

0 commit comments

Comments
 (0)