@@ -110,6 +110,9 @@ export abstract class _MatAutocompleteTriggerBase
110110 /** Old value of the native input. Used to work around issues with the `input` event on IE. */
111111 private _previousValue : string | number | null ;
112112
113+ /** Value of the input element when the panel was opened. */
114+ private _valueOnOpen : string | number | null ;
115+
113116 /** Strategy that is used to position the panel. */
114117 private _positionStrategy : FlexibleConnectedPositionStrategy ;
115118
@@ -561,7 +564,7 @@ export abstract class _MatAutocompleteTriggerBase
561564 // of the available options,
562565 // - if a valid string is entered after an invalid one.
563566 if ( this . panelOpen ) {
564- this . autocomplete . opened . emit ( ) ;
567+ this . _finalizeOpen ( ) ;
565568 } else {
566569 this . autocomplete . closed . emit ( ) ;
567570 }
@@ -578,6 +581,12 @@ export abstract class _MatAutocompleteTriggerBase
578581 ) ;
579582 }
580583
584+ /** Finalized the opening sequence once it's known that the panel will be shown. */
585+ private _finalizeOpen ( ) {
586+ this . _valueOnOpen = this . _element . nativeElement . value ;
587+ this . autocomplete . opened . emit ( ) ;
588+ }
589+
581590 /** Destroys the autocomplete suggestion panel. */
582591 private _destroyPanel ( ) : void {
583592 if ( this . _overlayRef ) {
@@ -616,14 +625,28 @@ export abstract class _MatAutocompleteTriggerBase
616625 * stemmed from the user.
617626 */
618627 private _setValueAndClose ( event : MatOptionSelectionChange | null ) : void {
628+ const panel = this . autocomplete ;
619629 const toSelect = event ? event . source : this . _pendingAutoselectedOption ;
620630
621631 if ( toSelect ) {
622632 this . _clearPreviousSelectedOption ( toSelect ) ;
623633 this . _assignOptionValue ( toSelect . value ) ;
634+ // TODO(crisbeto): this should wait until the animation is done, otherwise the value
635+ // gets reset while the panel is still animating which looks glitchy. It'll likely break
636+ // some tests to change it at this point.
624637 this . _onChange ( toSelect . value ) ;
625- this . autocomplete . _emitSelectEvent ( toSelect ) ;
638+ panel . _emitSelectEvent ( toSelect ) ;
626639 this . _element . nativeElement . focus ( ) ;
640+ } else if ( panel . requireSelection && this . _element . nativeElement . value !== this . _valueOnOpen ) {
641+ this . _clearPreviousSelectedOption ( null ) ;
642+ this . _assignOptionValue ( null ) ;
643+ // Wait for the animation to finish before clearing the form control value, otherwise
644+ // the options might change while the animation is running which looks glitchy.
645+ if ( panel . _animationDone ) {
646+ panel . _animationDone . pipe ( take ( 1 ) ) . subscribe ( ( ) => this . _onChange ( null ) ) ;
647+ } else {
648+ this . _onChange ( null ) ;
649+ }
627650 }
628651
629652 this . closePanel ( ) ;
@@ -633,13 +656,13 @@ export abstract class _MatAutocompleteTriggerBase
633656 * Clear any previous selected option and emit a selection change event for this option
634657 */
635658 private _clearPreviousSelectedOption ( skip : _MatOptionBase | null , emitEvent ?: boolean ) {
636- if ( this . autocomplete && this . autocomplete . options ) {
637- this . autocomplete . options . forEach ( option => {
638- if ( option !== skip && option . selected ) {
639- option . deselect ( emitEvent ) ;
640- }
641- } ) ;
642- }
659+ // Null checks are necessary here, because the autocomplete
660+ // or its options may not have been assigned yet.
661+ this . autocomplete ?. options ?. forEach ( option => {
662+ if ( option !== skip && option . selected ) {
663+ option . deselect ( emitEvent ) ;
664+ }
665+ } ) ;
643666 }
644667
645668 private _attachOverlay ( ) : void {
@@ -683,7 +706,7 @@ export abstract class _MatAutocompleteTriggerBase
683706 // We need to do an extra `panelOpen` check in here, because the
684707 // autocomplete won't be shown if there are no options.
685708 if ( this . panelOpen && wasOpen !== this . panelOpen ) {
686- this . autocomplete . opened . emit ( ) ;
709+ this . _finalizeOpen ( ) ;
687710 }
688711 }
689712
0 commit comments