From eac07bd11570173c0975287a2a3b690d37bf6cc9 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Fri, 27 Sep 2019 10:27:25 +0200 Subject: [PATCH] fix(select): highlighted option not updated if value is reset while closed Currently we support the same feature as the native `select` where users can change the value and the focused option while the panel is closed using the arrow keys. The problem is that if the user changes the selected option and the value gets reset, the active option doesn't get updated so next time they interact with the control, it'll pick up from the previous position. These changes add an extra call to reset the highlighted option if the value is reset. Fixes #17212. --- src/material/select/select.spec.ts | 28 ++++++++++++++++++++++++++++ src/material/select/select.ts | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts index 59c9b74ddec5..36eba828b355 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -296,6 +296,34 @@ describe('MatSelect', () => { flush(); })); + it('should go back to first option if value is reset after interacting using the' + + 'arrow keys on a closed select', fakeAsync(() => { + const formControl = fixture.componentInstance.control; + const options = fixture.componentInstance.options.toArray(); + + expect(formControl.value).toBeFalsy('Expected no initial value.'); + + dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); + flush(); + + expect(options[0].selected).toBe(true, 'Expected first option to be selected.'); + expect(formControl.value).toBe(options[0].value, + 'Expected value from first option to have been set on the model.'); + + formControl.reset(); + fixture.detectChanges(); + + expect(options[0].selected).toBe(false, 'Expected first option to be deselected.'); + expect(formControl.value).toBeFalsy('Expected value to be reset.'); + + dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); + flush(); + + expect(options[0].selected).toBe(true, 'Expected first option to be selected again.'); + expect(formControl.value).toBe(options[0].value, + 'Expected value from first option to have been set on the model again.'); + })); + it('should select first/last options via the HOME/END keys on a closed select', fakeAsync(() => { const formControl = fixture.componentInstance.control; diff --git a/src/material/select/select.ts b/src/material/select/select.ts index 3a357d1b871f..ec20a48e7685 100644 --- a/src/material/select/select.ts +++ b/src/material/select/select.ts @@ -858,6 +858,10 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit, // mode, because we don't know what option the user interacted with last. if (correspondingOption) { this._keyManager.setActiveItem(correspondingOption); + } else if (!this.panelOpen) { + // Otherwise reset the highlighted option. Note that we only want to do this while + // closed, because doing it while open can shift the user's focus unnecessarily. + this._keyManager.setActiveItem(-1); } }