@@ -112,6 +112,9 @@ export abstract class _MatAutocompleteTriggerBase
112
112
/** Old value of the native input. Used to work around issues with the `input` event on IE. */
113
113
private _previousValue : string | number | null ;
114
114
115
+ /** Value of the input element when the panel was opened. */
116
+ private _valueOnOpen : string | number | null ;
117
+
115
118
/** Strategy that is used to position the panel. */
116
119
private _positionStrategy : FlexibleConnectedPositionStrategy ;
117
120
@@ -565,7 +568,7 @@ export abstract class _MatAutocompleteTriggerBase
565
568
// of the available options,
566
569
// - if a valid string is entered after an invalid one.
567
570
if ( this . panelOpen ) {
568
- this . autocomplete . opened . emit ( ) ;
571
+ this . _emitOpened ( ) ;
569
572
} else {
570
573
this . autocomplete . closed . emit ( ) ;
571
574
}
@@ -582,6 +585,15 @@ export abstract class _MatAutocompleteTriggerBase
582
585
) ;
583
586
}
584
587
588
+ /**
589
+ * Emits the opened event once it's known that the panel will be shown and stores
590
+ * the state of the trigger right before the opening sequence was finished.
591
+ */
592
+ private _emitOpened ( ) {
593
+ this . _valueOnOpen = this . _element . nativeElement . value ;
594
+ this . autocomplete . opened . emit ( ) ;
595
+ }
596
+
585
597
/** Destroys the autocomplete suggestion panel. */
586
598
private _destroyPanel ( ) : void {
587
599
if ( this . _overlayRef ) {
@@ -620,14 +632,28 @@ export abstract class _MatAutocompleteTriggerBase
620
632
* stemmed from the user.
621
633
*/
622
634
private _setValueAndClose ( event : MatOptionSelectionChange | null ) : void {
635
+ const panel = this . autocomplete ;
623
636
const toSelect = event ? event . source : this . _pendingAutoselectedOption ;
624
637
625
638
if ( toSelect ) {
626
639
this . _clearPreviousSelectedOption ( toSelect ) ;
627
640
this . _assignOptionValue ( toSelect . value ) ;
641
+ // TODO(crisbeto): this should wait until the animation is done, otherwise the value
642
+ // gets reset while the panel is still animating which looks glitchy. It'll likely break
643
+ // some tests to change it at this point.
628
644
this . _onChange ( toSelect . value ) ;
629
- this . autocomplete . _emitSelectEvent ( toSelect ) ;
645
+ panel . _emitSelectEvent ( toSelect ) ;
630
646
this . _element . nativeElement . focus ( ) ;
647
+ } else if ( panel . requireSelection && this . _element . nativeElement . value !== this . _valueOnOpen ) {
648
+ this . _clearPreviousSelectedOption ( null ) ;
649
+ this . _assignOptionValue ( null ) ;
650
+ // Wait for the animation to finish before clearing the form control value, otherwise
651
+ // the options might change while the animation is running which looks glitchy.
652
+ if ( panel . _animationDone ) {
653
+ panel . _animationDone . pipe ( take ( 1 ) ) . subscribe ( ( ) => this . _onChange ( null ) ) ;
654
+ } else {
655
+ this . _onChange ( null ) ;
656
+ }
631
657
}
632
658
633
659
this . closePanel ( ) ;
@@ -637,13 +663,13 @@ export abstract class _MatAutocompleteTriggerBase
637
663
* Clear any previous selected option and emit a selection change event for this option
638
664
*/
639
665
private _clearPreviousSelectedOption ( skip : _MatOptionBase | null , emitEvent ?: boolean ) {
640
- if ( this . autocomplete && this . autocomplete . options ) {
641
- this . autocomplete . options . forEach ( option => {
642
- if ( option !== skip && option . selected ) {
643
- option . deselect ( emitEvent ) ;
644
- }
645
- } ) ;
646
- }
666
+ // Null checks are necessary here, because the autocomplete
667
+ // or its options may not have been assigned yet.
668
+ this . autocomplete ?. options ?. forEach ( option => {
669
+ if ( option !== skip && option . selected ) {
670
+ option . deselect ( emitEvent ) ;
671
+ }
672
+ } ) ;
647
673
}
648
674
649
675
private _attachOverlay ( ) : void {
@@ -686,7 +712,7 @@ export abstract class _MatAutocompleteTriggerBase
686
712
// We need to do an extra `panelOpen` check in here, because the
687
713
// autocomplete won't be shown if there are no options.
688
714
if ( this . panelOpen && wasOpen !== this . panelOpen ) {
689
- this . autocomplete . opened . emit ( ) ;
715
+ this . _emitOpened ( ) ;
690
716
}
691
717
}
692
718
0 commit comments