Skip to content

Commit e5f62b7

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 177a433 commit e5f62b7

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -488,24 +488,32 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
488488

489489
// When the zone is stable initially, and when the option list changes...
490490
return merge(firstStable, optionChanges)
491-
.pipe(
492-
// create a new stream of panelClosingActions, replacing any previous streams
493-
// that were created, and flatten it so our stream only emits closing events...
494-
switchMap(() => {
495-
this._resetActiveItem();
496-
this.autocomplete._setVisibility();
497-
498-
if (this.panelOpen) {
499-
this._overlayRef!.updatePosition();
500-
}
501-
502-
return this.panelClosingActions;
503-
}),
504-
// when the first closing event occurs...
505-
take(1)
506-
)
507-
// set the value, close the panel, and complete.
508-
.subscribe(event => this._setValueAndClose(event));
491+
.pipe(
492+
// create a new stream of panelClosingActions, replacing any previous streams
493+
// that were created, and flatten it so our stream only emits closing events...
494+
switchMap(() => {
495+
const wasOpen = this.panelOpen;
496+
this._resetActiveItem();
497+
this.autocomplete._setVisibility();
498+
499+
if (this.panelOpen) {
500+
this._overlayRef!.updatePosition();
501+
502+
// If the `panelOpen` state changed, we need to make sure to emit the `opened`
503+
// event, because we may not have emitted it when the panel was attached. This
504+
// can happen if the users opens the panel and there are no options, but the
505+
// options come in slightly later or as a result of the value changing.
506+
if (wasOpen !== this.panelOpen) {
507+
this.autocomplete.opened.emit();
508+
}
509+
}
510+
511+
return this.panelClosingActions;
512+
}),
513+
// when the first closing event occurs...
514+
take(1))
515+
// set the value, close the panel, and complete.
516+
.subscribe(event => this._setValueAndClose(event));
509517
}
510518

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

src/lib/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)