Skip to content

Commit cb206be

Browse files
authored
fix(material/autocomplete): always emit closed event (#24642)
Currently, the autocomplete does not emit a `closed` event if the user clicks outside the input field after having entered a string that did not match any option. Moreover, when entering a valid string after an invalid one, the `opened` event is emitted again without a previous `closed` event. This PR ensures that a `closed` event is emitted every time the panel is closed
1 parent 853d2cc commit cb206be

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/material-experimental/mdc-autocomplete/autocomplete.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,6 +2825,25 @@ describe('MDC-based MatAutocomplete', () => {
28252825
expect(closedSpy).toHaveBeenCalledTimes(1);
28262826
}));
28272827

2828+
it('should emit a closed event if no option is displayed', fakeAsync(() => {
2829+
const {openedSpy, closedSpy} = fixture.componentInstance;
2830+
const input: HTMLInputElement = fixture.nativeElement.querySelector('input');
2831+
2832+
typeInElement(input, 'Alabama'); // Valid option
2833+
fixture.detectChanges();
2834+
tick();
2835+
2836+
expect(openedSpy).toHaveBeenCalledTimes(1);
2837+
expect(closedSpy).toHaveBeenCalledTimes(0);
2838+
2839+
typeInElement(input, '_x'); // Invalidate option to 'Alabama_x'
2840+
fixture.detectChanges();
2841+
tick();
2842+
2843+
expect(openedSpy).toHaveBeenCalledTimes(1);
2844+
expect(closedSpy).toHaveBeenCalledTimes(1);
2845+
}));
2846+
28282847
it(
28292848
'should clear the input if the user presses escape while there was a pending ' +
28302849
'auto selection and there is no previous value',

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -537,13 +537,20 @@ export abstract class _MatAutocompleteTriggerBase
537537

538538
if (this.panelOpen) {
539539
this._overlayRef!.updatePosition();
540+
}
540541

541-
// If the `panelOpen` state changed, we need to make sure to emit the `opened`
542-
// event, because we may not have emitted it when the panel was attached. This
543-
// can happen if the users opens the panel and there are no options, but the
544-
// options come in slightly later or as a result of the value changing.
545-
if (wasOpen !== this.panelOpen) {
542+
if (wasOpen !== this.panelOpen) {
543+
// If the `panelOpen` state changed, we need to make sure to emit the `opened` or
544+
// `closed` event, because we may not have emitted it. This can happen
545+
// - if the users opens the panel and there are no options, but the
546+
// options come in slightly later or as a result of the value changing,
547+
// - if the panel is closed after the user entered a string that did not match any
548+
// of the available options,
549+
// - if a valid string is entered after an invalid one.
550+
if (this.panelOpen) {
546551
this.autocomplete.opened.emit();
552+
} else {
553+
this.autocomplete.closed.emit();
547554
}
548555
}
549556
});

src/material/autocomplete/autocomplete.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,6 +2827,25 @@ describe('MatAutocomplete', () => {
28272827
expect(closedSpy).toHaveBeenCalledTimes(1);
28282828
}));
28292829

2830+
it('should emit a closed event if no option is displayed', fakeAsync(() => {
2831+
const {openedSpy, closedSpy} = fixture.componentInstance;
2832+
const input: HTMLInputElement = fixture.nativeElement.querySelector('input');
2833+
2834+
typeInElement(input, 'Alabama'); // Valid option
2835+
fixture.detectChanges();
2836+
tick();
2837+
2838+
expect(openedSpy).toHaveBeenCalledTimes(1);
2839+
expect(closedSpy).toHaveBeenCalledTimes(0);
2840+
2841+
typeInElement(input, '_x'); // Invalidate option to 'Alabama_x'
2842+
fixture.detectChanges();
2843+
tick();
2844+
2845+
expect(openedSpy).toHaveBeenCalledTimes(1);
2846+
expect(closedSpy).toHaveBeenCalledTimes(1);
2847+
}));
2848+
28302849
it(
28312850
'should clear the input if the user presses escape while there was a pending ' +
28322851
'auto selection and there is no previous value',

0 commit comments

Comments
 (0)