Skip to content

Commit 5df5791

Browse files
committed
fix(connected-overlay): better handling of dynamic content
* Refactors the `ConnectedPositionStrategy` to be able to use `right` and `bottom` to position the panel. This will allow the element to keep its position automatically, even if the element's size changes. * Removes the uses of the `FakeViewportRuler` in some of the unit tests since it doesn't work very well when the element is positioned relatively to the right edge of the screen. * Rounds down the values when testing positioning. This is necessary, because some browsers (particularly Chrome on Windows) can have some subpixel deviations. Fixes angular#4155.
1 parent b4e8c7d commit 5df5791

File tree

6 files changed

+198
-225
lines changed

6 files changed

+198
-225
lines changed

src/lib/autocomplete/autocomplete.spec.ts

+8-13
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
1818
import {Subscription} from 'rxjs/Subscription';
1919
import {ENTER, DOWN_ARROW, SPACE, UP_ARROW, HOME, END} from '../core/keyboard/keycodes';
2020
import {MdOption} from '../core/option/option';
21-
import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
22-
import {FakeViewportRuler} from '../core/overlay/position/fake-viewport-ruler';
2321
import {MdAutocomplete} from './autocomplete';
2422
import {MdInputContainer} from '../input/input-container';
2523
import {Observable} from 'rxjs/Observable';
@@ -65,10 +63,7 @@ describe('MdAutocomplete', () => {
6563

6664
return {getContainerElement: () => overlayContainerElement};
6765
}},
68-
{provide: Dir, useFactory: () => {
69-
return {value: dir};
70-
}},
71-
{provide: ViewportRuler, useClass: FakeViewportRuler},
66+
{provide: Dir, useFactory: () => ({value: dir})},
7267
{provide: ScrollDispatcher, useFactory: () => {
7368
return {scrolled: (delay: number, callback: () => any) => {
7469
return scrolledSubject.asObservable().subscribe(callback);
@@ -929,8 +924,8 @@ describe('MdAutocomplete', () => {
929924
const panelTop = panel.getBoundingClientRect().top;
930925

931926
// Panel is offset by 6px in styles so that the underline has room to display.
932-
expect((inputBottom + 6).toFixed(1))
933-
.toEqual(panelTop.toFixed(1), `Expected panel top to match input bottom by default.`);
927+
expect(Math.floor(inputBottom + 6))
928+
.toEqual(Math.floor(panelTop), `Expected panel top to match input bottom by default.`);
934929
expect(fixture.componentInstance.trigger.autocomplete.positionY)
935930
.toEqual('below', `Expected autocomplete positionY to default to below.`);
936931
});
@@ -952,7 +947,7 @@ describe('MdAutocomplete', () => {
952947
const panel = overlayContainerElement.querySelector('.mat-autocomplete-panel');
953948
const panelTop = panel.getBoundingClientRect().top;
954949

955-
expect((inputBottom + 6).toFixed(1)).toEqual(panelTop.toFixed(1),
950+
expect(Math.floor(inputBottom + 6)).toEqual(Math.floor(panelTop),
956951
'Expected panel top to match input bottom after scrolling.');
957952

958953
document.body.removeChild(spacer);
@@ -971,8 +966,8 @@ describe('MdAutocomplete', () => {
971966
const panelBottom = panel.getBoundingClientRect().bottom;
972967

973968
// Panel is offset by 24px in styles so that the label has room to display.
974-
expect((inputTop - 24).toFixed(1))
975-
.toEqual(panelBottom.toFixed(1), `Expected panel to fall back to above position.`);
969+
expect(Math.floor(inputTop - 24))
970+
.toEqual(Math.floor(panelBottom), `Expected panel to fall back to above position.`);
976971
expect(fixture.componentInstance.trigger.autocomplete.positionY)
977972
.toEqual('above', `Expected autocomplete positionY to be "above" if panel won't fit.`);
978973
});
@@ -994,8 +989,8 @@ describe('MdAutocomplete', () => {
994989
const panelBottom = panel.getBoundingClientRect().bottom;
995990

996991
// Panel is offset by 24px in styles so that the label has room to display.
997-
expect((inputTop - 24).toFixed(1))
998-
.toEqual(panelBottom.toFixed(1), `Expected panel to stay aligned after filtering.`);
992+
expect(Math.floor(inputTop - 24))
993+
.toEqual(Math.floor(panelBottom), `Expected panel to stay aligned after filtering.`);
999994
expect(fixture.componentInstance.trigger.autocomplete.positionY)
1000995
.toEqual('above', `Expected autocomplete positionY to be "above" if panel won't fit.`);
1001996
});

src/lib/core/overlay/_overlay.scss

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
// The container should be the size of the viewport.
1010
top: 0;
1111
left: 0;
12-
height: 100%;
13-
width: 100%;
12+
13+
// Note: we prefer viewport units, because they aren't being offset by the global scrollbar.
14+
height: 100vh;
15+
width: 100vw;
1416
}
1517

1618
// The overlay-container is an invisible element which contains all individual overlays.

0 commit comments

Comments
 (0)