Skip to content

Commit 525ce1e

Browse files
crisbetoandrewseguin
authored andcommitted
fix(connected-overlay): better handling of dynamic content (#4250)
* 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 #4155. * refactor: move new logic into _setElementPosition method
1 parent f8a2860 commit 525ce1e

File tree

6 files changed

+307
-233
lines changed

6 files changed

+307
-233
lines changed

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 8 additions & 13 deletions
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);
@@ -933,8 +928,8 @@ describe('MdAutocomplete', () => {
933928
const panelTop = panel.getBoundingClientRect().top;
934929

935930
// Panel is offset by 6px in styles so that the underline has room to display.
936-
expect((inputBottom + 6).toFixed(1))
937-
.toEqual(panelTop.toFixed(1), `Expected panel top to match input bottom by default.`);
931+
expect(Math.floor(inputBottom + 6))
932+
.toEqual(Math.floor(panelTop), `Expected panel top to match input bottom by default.`);
938933
expect(fixture.componentInstance.trigger.autocomplete.positionY)
939934
.toEqual('below', `Expected autocomplete positionY to default to below.`);
940935
});
@@ -956,7 +951,7 @@ describe('MdAutocomplete', () => {
956951
const panel = overlayContainerElement.querySelector('.mat-autocomplete-panel');
957952
const panelTop = panel.getBoundingClientRect().top;
958953

959-
expect((inputBottom + 6).toFixed(1)).toEqual(panelTop.toFixed(1),
954+
expect(Math.floor(inputBottom + 6)).toEqual(Math.floor(panelTop),
960955
'Expected panel top to match input bottom after scrolling.');
961956

962957
document.body.removeChild(spacer);
@@ -975,8 +970,8 @@ describe('MdAutocomplete', () => {
975970
const panelBottom = panel.getBoundingClientRect().bottom;
976971

977972
// Panel is offset by 24px in styles so that the label has room to display.
978-
expect((inputTop - 24).toFixed(1))
979-
.toEqual(panelBottom.toFixed(1), `Expected panel to fall back to above position.`);
973+
expect(Math.floor(inputTop - 24))
974+
.toEqual(Math.floor(panelBottom), `Expected panel to fall back to above position.`);
980975
expect(fixture.componentInstance.trigger.autocomplete.positionY)
981976
.toEqual('above', `Expected autocomplete positionY to be "above" if panel won't fit.`);
982977
});
@@ -998,8 +993,8 @@ describe('MdAutocomplete', () => {
998993
const panelBottom = panel.getBoundingClientRect().bottom;
999994

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

src/lib/core/overlay/_overlay.scss

Lines changed: 4 additions & 2 deletions
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)