Skip to content

Commit face478

Browse files
committed
fix(autocomplete): not emitting opened event if options come in after open
Fixes `mat-autocomplete` not emitting its `opened` event if it is opened without any options and then the options come in at a later point. Fixes #15573.
1 parent 3712b8f commit face478

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -510,24 +510,32 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnChanges,
510510

511511
// When the zone is stable initially, and when the option list changes...
512512
return merge(firstStable, optionChanges)
513-
.pipe(
514-
// create a new stream of panelClosingActions, replacing any previous streams
515-
// that were created, and flatten it so our stream only emits closing events...
516-
switchMap(() => {
517-
this._resetActiveItem();
518-
this.autocomplete._setVisibility();
519-
520-
if (this.panelOpen) {
521-
this._overlayRef!.updatePosition();
522-
}
523-
524-
return this.panelClosingActions;
525-
}),
526-
// when the first closing event occurs...
527-
take(1)
528-
)
529-
// set the value, close the panel, and complete.
530-
.subscribe(event => this._setValueAndClose(event));
513+
.pipe(
514+
// create a new stream of panelClosingActions, replacing any previous streams
515+
// that were created, and flatten it so our stream only emits closing events...
516+
switchMap(() => {
517+
const wasOpen = this.panelOpen;
518+
this._resetActiveItem();
519+
this.autocomplete._setVisibility();
520+
521+
if (this.panelOpen) {
522+
this._overlayRef!.updatePosition();
523+
524+
// If the `panelOpen` state changed, we need to make sure to emit the `opened`
525+
// event, because we may not have emitted it when the panel was attached. This
526+
// can happen if the users opens the panel and there are no options, but the
527+
// options come in slightly later or as a result of the value changing.
528+
if (wasOpen !== this.panelOpen) {
529+
this.autocomplete.opened.emit();
530+
}
531+
}
532+
533+
return this.panelClosingActions;
534+
}),
535+
// when the first closing event occurs...
536+
take(1))
537+
// set the value, close the panel, and complete.
538+
.subscribe(event => this._setValueAndClose(event));
531539
}
532540

533541
/** Destroys the autocomplete suggestion panel. */

src/material/autocomplete/autocomplete.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,25 @@ describe('MatAutocomplete', () => {
421421
expect(fixture.componentInstance.openedSpy).not.toHaveBeenCalled();
422422
});
423423

424+
it('should emit the `opened` event if the options come in after the panel is shown',
425+
fakeAsync(() => {
426+
fixture.componentInstance.filteredStates = fixture.componentInstance.states = [];
427+
fixture.detectChanges();
428+
429+
fixture.componentInstance.trigger.openPanel();
430+
fixture.detectChanges();
431+
432+
expect(fixture.componentInstance.openedSpy).not.toHaveBeenCalled();
433+
434+
fixture.componentInstance.filteredStates = fixture.componentInstance.states =
435+
[{name: 'California', code: 'CA'}];
436+
fixture.detectChanges();
437+
tick();
438+
fixture.detectChanges();
439+
440+
expect(fixture.componentInstance.openedSpy).toHaveBeenCalled();
441+
}));
442+
424443
it('should not emit the opened event multiple times while typing', fakeAsync(() => {
425444
fixture.componentInstance.trigger.openPanel();
426445
fixture.detectChanges();

0 commit comments

Comments
 (0)