Skip to content

Commit d6ba25f

Browse files
crisbetovivian-hu-zz
authored andcommitted
fix(select): handle home and end keys on closed select (#13278)
Moves the selection to the first/last item when pressing home/end on a closed `mat-select`, similarly to a native `select`.
1 parent 01b18c0 commit d6ba25f

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/lib/select/select.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,29 @@ describe('MatSelect', () => {
293293
'Expected value from second option to have been set on the model.');
294294
}));
295295

296+
it('should select first/last options via the HOME/END keys on a closed select',
297+
fakeAsync(() => {
298+
const formControl = fixture.componentInstance.control;
299+
const firstOption = fixture.componentInstance.options.first;
300+
const lastOption = fixture.componentInstance.options.last;
301+
302+
expect(formControl.value).toBeFalsy('Expected no initial value.');
303+
304+
const endEvent = dispatchKeyboardEvent(select, 'keydown', END);
305+
306+
expect(endEvent.defaultPrevented).toBe(true);
307+
expect(lastOption.selected).toBe(true, 'Expected last option to be selected.');
308+
expect(formControl.value).toBe(lastOption.value,
309+
'Expected value from last option to have been set on the model.');
310+
311+
const homeEvent = dispatchKeyboardEvent(select, 'keydown', HOME);
312+
313+
expect(homeEvent.defaultPrevented).toBe(true);
314+
expect(firstOption.selected).toBe(true, 'Expected first option to be selected.');
315+
expect(formControl.value).toBe(firstOption.value,
316+
'Expected value from first option to have been set on the model.');
317+
}));
318+
296319
it('should resume focus from selected item after selecting via click', fakeAsync(() => {
297320
const formControl = fixture.componentInstance.control;
298321
const options = fixture.componentInstance.options.toArray();

src/lib/select/select.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,15 +691,21 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
691691
private _handleClosedKeydown(event: KeyboardEvent): void {
692692
const keyCode = event.keyCode;
693693
const isArrowKey = keyCode === DOWN_ARROW || keyCode === UP_ARROW ||
694-
keyCode === LEFT_ARROW || keyCode === RIGHT_ARROW;
694+
keyCode === LEFT_ARROW || keyCode === RIGHT_ARROW;
695695
const isOpenKey = keyCode === ENTER || keyCode === SPACE;
696+
const manager = this._keyManager;
696697

697698
// Open the select on ALT + arrow key to match the native <select>
698699
if (isOpenKey || ((this.multiple || event.altKey) && isArrowKey)) {
699700
event.preventDefault(); // prevents the page from scrolling down when pressing space
700701
this.open();
701702
} else if (!this.multiple) {
702-
this._keyManager.onKeydown(event);
703+
if (keyCode === HOME || keyCode === END) {
704+
keyCode === HOME ? manager.setFirstItemActive() : manager.setLastItemActive();
705+
event.preventDefault();
706+
} else {
707+
manager.onKeydown(event);
708+
}
703709
}
704710
}
705711

0 commit comments

Comments
 (0)