Skip to content

Commit 739ef05

Browse files
committed
refactor(select,autocomplete): consolidate logic for scrolling options into view
Combines some duplicated logic for determining how to scroll an option into view into a single place so it's easier to maintain.
1 parent 3352201 commit 739ef05

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -374,20 +374,17 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
374374
* not adjusted.
375375
*/
376376
private _scrollToOption(): void {
377-
const activeOptionIndex = this.autocomplete._keyManager.activeItemIndex || 0;
378-
const labelCount = MatOption.countGroupLabelsBeforeOption(activeOptionIndex,
377+
const index = this.autocomplete._keyManager.activeItemIndex || 0;
378+
const labelCount = MatOption.countGroupLabelsBeforeOption(index,
379379
this.autocomplete.options, this.autocomplete.optionGroups);
380-
const optionOffset = (activeOptionIndex + labelCount) * AUTOCOMPLETE_OPTION_HEIGHT;
381-
const panelTop = this.autocomplete._getScrollTop();
382-
383-
if (optionOffset < panelTop) {
384-
// Scroll up to reveal selected option scrolled above the panel top
385-
this.autocomplete._setScrollTop(optionOffset);
386-
} else if (optionOffset + AUTOCOMPLETE_OPTION_HEIGHT > panelTop + AUTOCOMPLETE_PANEL_HEIGHT) {
387-
// Scroll down to reveal selected option scrolled below the panel bottom
388-
const newScrollTop = optionOffset - AUTOCOMPLETE_PANEL_HEIGHT + AUTOCOMPLETE_OPTION_HEIGHT;
389-
this.autocomplete._setScrollTop(Math.max(0, newScrollTop));
390-
}
380+
381+
const newScrollPosition = MatOption.getScrollPosition(
382+
index + labelCount,
383+
AUTOCOMPLETE_OPTION_HEIGHT,
384+
this.autocomplete._getScrollTop(),
385+
AUTOCOMPLETE_PANEL_HEIGHT);
386+
387+
this.autocomplete._setScrollTop(newScrollPosition);
391388
}
392389

393390
/**

src/lib/core/option/option.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,26 @@ export class MatOption implements AfterViewChecked {
273273
return 0;
274274
}
275275

276+
/**
277+
* Determines the position to which to scroll a panel in order for an option to be into view.
278+
* @param optionIndex Index of the option to be scrolled into the view.
279+
* @param optionHeight Height of the options.
280+
* @param currentScrollPosition Current scroll position of the panel.
281+
* @param panelHeight Height of the panel.
282+
*/
283+
static getScrollPosition(optionIndex: number, optionHeight: number, currentScrollPosition: number,
284+
panelHeight: number): number {
285+
const optionOffset = optionIndex * optionHeight;
286+
287+
if (optionOffset < currentScrollPosition) {
288+
return optionOffset;
289+
}
290+
291+
if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
292+
return Math.max(0, optionOffset - panelHeight + optionHeight);
293+
}
294+
295+
return currentScrollPosition;
296+
}
297+
276298
}

src/lib/select/select.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -971,19 +971,15 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
971971

972972
/** Scrolls the active option into view. */
973973
private _scrollActiveOptionIntoView(): void {
974-
const itemHeight = this._getItemHeight();
975974
const activeOptionIndex = this._keyManager.activeItemIndex || 0;
976975
const labelCount = MatOption.countGroupLabelsBeforeOption(activeOptionIndex,
977976
this.options, this.optionGroups);
978-
const scrollOffset = (activeOptionIndex + labelCount) * itemHeight;
979-
const panelTop = this.panel.nativeElement.scrollTop;
980-
981-
if (scrollOffset < panelTop) {
982-
this.panel.nativeElement.scrollTop = scrollOffset;
983-
} else if (scrollOffset + itemHeight > panelTop + SELECT_PANEL_MAX_HEIGHT) {
984-
this.panel.nativeElement.scrollTop =
985-
Math.max(0, scrollOffset - SELECT_PANEL_MAX_HEIGHT + itemHeight);
986-
}
977+
978+
this.panel.nativeElement.scrollTop = MatOption.getScrollPosition(
979+
activeOptionIndex + labelCount,
980+
this._getItemHeight(),
981+
this.panel.nativeElement.scrollTop,
982+
SELECT_PANEL_MAX_HEIGHT);
987983
}
988984

989985
/** Focuses the select element. */

0 commit comments

Comments
 (0)