@@ -136,9 +136,28 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
136136 /** Subscription to viewport size changes. */
137137 private _viewportSubscription = Subscription . EMPTY ;
138138
139+ /**
140+ * Whether the autocomplete can open the next time it is focused. Used to prevent a focused,
141+ * closed autocomplete from being reopened if the user switches to another browser tab and then
142+ * comes back.
143+ */
144+ private _canOpenOnNextFocus = true ;
145+
139146 /** Stream of keyboard events that can close the panel. */
140147 private readonly _closeKeyEventStream = new Subject < void > ( ) ;
141148
149+ /**
150+ * Event handler for when the window is blurred. Needs to be an
151+ * arrow function in order to preserve the context.
152+ */
153+ private _windowBlurHandler = ( ) => {
154+ // If the user blurred the window while the autocomplete is focused, it means that it'll be
155+ // refocused when they come back. In this case we want to skip the first focus event, if the
156+ // pane was closed, in order to avoid reopening it unintentionally.
157+ this . _canOpenOnNextFocus =
158+ document . activeElement !== this . _element . nativeElement || this . panelOpen ;
159+ }
160+
142161 /** `View -> model callback called when value changes` */
143162 _onChange : ( value : any ) => void = ( ) => { } ;
144163
@@ -179,9 +198,20 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
179198 @Optional ( ) @Host ( ) private _formField : MatFormField ,
180199 @Optional ( ) @Inject ( DOCUMENT ) private _document : any ,
181200 // @breaking -change 7.0.0 Make `_viewportRuler` required.
182- private _viewportRuler ?: ViewportRuler ) { }
201+ private _viewportRuler ?: ViewportRuler ) {
202+
203+ if ( typeof window !== 'undefined' ) {
204+ _zone . runOutsideAngular ( ( ) => {
205+ window . addEventListener ( 'blur' , this . _windowBlurHandler ) ;
206+ } ) ;
207+ }
208+ }
183209
184210 ngOnDestroy ( ) {
211+ if ( typeof window !== 'undefined' ) {
212+ window . removeEventListener ( 'blur' , this . _windowBlurHandler ) ;
213+ }
214+
185215 this . _viewportSubscription . unsubscribe ( ) ;
186216 this . _componentDestroyed = true ;
187217 this . _destroyPanel ( ) ;
@@ -386,7 +416,9 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
386416 }
387417
388418 _handleFocus ( ) : void {
389- if ( this . _canOpen ( ) ) {
419+ if ( ! this . _canOpenOnNextFocus ) {
420+ this . _canOpenOnNextFocus = true ;
421+ } else if ( this . _canOpen ( ) ) {
390422 this . _previousValue = this . _element . nativeElement . value ;
391423 this . _attachOverlay ( ) ;
392424 this . _floatLabel ( true ) ;
@@ -633,5 +665,4 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
633665 const element : HTMLInputElement = this . _element . nativeElement ;
634666 return ! element . readOnly && ! element . disabled && ! this . _autocompleteDisabled ;
635667 }
636-
637668}
0 commit comments