@@ -135,9 +135,28 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
135
135
/** Subscription to viewport size changes. */
136
136
private _viewportSubscription = Subscription . EMPTY ;
137
137
138
+ /**
139
+ * Whether the autocomplete can open the next time it is focused. Used to prevent a focused,
140
+ * closed autocomplete from being reopened if the user switches to another browser tab and then
141
+ * comes back.
142
+ */
143
+ private _canOpenOnNextFocus = true ;
144
+
138
145
/** Stream of keyboard events that can close the panel. */
139
146
private readonly _closeKeyEventStream = new Subject < void > ( ) ;
140
147
148
+ /**
149
+ * Event handler for when the window is blurred. Needs to be an
150
+ * arrow function in order to preserve the context.
151
+ */
152
+ private _windowBlurHandler = ( ) => {
153
+ // If the user blurred the window while the autocomplete is focused, it means that it'll be
154
+ // refocused when they come back. In this case we want to skip the first focus event, if the
155
+ // pane was closed, in order to avoid reopening it unintentionally.
156
+ this . _canOpenOnNextFocus =
157
+ document . activeElement !== this . _element . nativeElement || this . panelOpen ;
158
+ }
159
+
141
160
/** `View -> model callback called when value changes` */
142
161
_onChange : ( value : any ) => void = ( ) => { } ;
143
162
@@ -178,9 +197,20 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
178
197
@Optional ( ) @Host ( ) private _formField : MatFormField ,
179
198
@Optional ( ) @Inject ( DOCUMENT ) private _document : any ,
180
199
// @breaking -change 7.0.0 Make `_viewportRuler` required.
181
- private _viewportRuler ?: ViewportRuler ) { }
200
+ private _viewportRuler ?: ViewportRuler ) {
201
+
202
+ if ( typeof window !== 'undefined' ) {
203
+ _zone . runOutsideAngular ( ( ) => {
204
+ window . addEventListener ( 'blur' , this . _windowBlurHandler ) ;
205
+ } ) ;
206
+ }
207
+ }
182
208
183
209
ngOnDestroy ( ) {
210
+ if ( typeof window !== 'undefined' ) {
211
+ window . removeEventListener ( 'blur' , this . _windowBlurHandler ) ;
212
+ }
213
+
184
214
this . _viewportSubscription . unsubscribe ( ) ;
185
215
this . _componentDestroyed = true ;
186
216
this . _destroyPanel ( ) ;
@@ -375,7 +405,9 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
375
405
}
376
406
377
407
_handleFocus ( ) : void {
378
- if ( this . _canOpen ( ) ) {
408
+ if ( ! this . _canOpenOnNextFocus ) {
409
+ this . _canOpenOnNextFocus = true ;
410
+ } else if ( this . _canOpen ( ) ) {
379
411
this . _previousValue = this . _element . nativeElement . value ;
380
412
this . _attachOverlay ( ) ;
381
413
this . _floatLabel ( true ) ;
@@ -612,5 +644,4 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
612
644
const element : HTMLInputElement = this . _element . nativeElement ;
613
645
return ! element . readOnly && ! element . disabled && ! this . _autocompleteDisabled ;
614
646
}
615
-
616
647
}
0 commit comments