Skip to content

Commit

Permalink
fix(autocomplete): restore focus after emitting option selected event
Browse files Browse the repository at this point in the history
Currently we restore focus to the input and then we emit the change event, but we have a report that it may be making some use cases more difficult. From what I can tell, this shouldn't have much of an impact on existing users so these changes swap the order so that the focus event is last.

Fixes angular#18650.
  • Loading branch information
crisbeto committed Mar 4, 2020
1 parent 9343d08 commit 0129a48
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
12 changes: 7 additions & 5 deletions src/material/autocomplete/autocomplete-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,12 +595,14 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, AfterViewIn
* stemmed from the user.
*/
private _setValueAndClose(event: MatOptionSelectionChange | null): void {
if (event && event.source) {
this._clearPreviousSelectedOption(event.source);
this._setTriggerValue(event.source.value);
this._onChange(event.source.value);
const source = event && event.source;

if (source) {
this._clearPreviousSelectedOption(source);
this._setTriggerValue(source.value);
this._onChange(source.value);
this.autocomplete._emitSelectEvent(source);
this._element.nativeElement.focus();
this.autocomplete._emitSelectEvent(event.source);
}

this.closePanel();
Expand Down
22 changes: 22 additions & 0 deletions src/material/autocomplete/autocomplete.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,28 @@ describe('MatAutocomplete', () => {
expect(event.option.value).toBe('Washington');
}));

it('should refocus the input after the selection event is emitted', fakeAsync(() => {
const events: string[] = [];
const fixture = createComponent(AutocompleteWithSelectEvent);
fixture.detectChanges();
const input = fixture.nativeElement.querySelector('input');

fixture.componentInstance.trigger.openPanel();
zone.simulateZoneExit();
fixture.detectChanges();

const options =
overlayContainerElement.querySelectorAll('mat-option') as NodeListOf<HTMLElement>;
spyOn(input, 'focus').and.callFake(() => events.push('focus'));
fixture.componentInstance.optionSelected.and.callFake(() => events.push('select'));

options[1].click();
tick();
fixture.detectChanges();

expect(events).toEqual(['select', 'focus']);
}));

it('should emit an event when a newly-added option is selected', fakeAsync(() => {
let fixture = createComponent(AutocompleteWithSelectEvent);

Expand Down

0 comments on commit 0129a48

Please sign in to comment.