@@ -136,9 +136,28 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
136
136
/** Subscription to viewport size changes. */
137
137
private _viewportSubscription = Subscription . EMPTY ;
138
138
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
+
139
146
/** Stream of keyboard events that can close the panel. */
140
147
private readonly _closeKeyEventStream = new Subject < void > ( ) ;
141
148
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
+
142
161
/** `View -> model callback called when value changes` */
143
162
_onChange : ( value : any ) => void = ( ) => { } ;
144
163
@@ -179,9 +198,20 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
179
198
@Optional ( ) @Host ( ) private _formField : MatFormField ,
180
199
@Optional ( ) @Inject ( DOCUMENT ) private _document : any ,
181
200
// @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
+ }
183
209
184
210
ngOnDestroy ( ) {
211
+ if ( typeof window !== 'undefined' ) {
212
+ window . removeEventListener ( 'blur' , this . _windowBlurHandler ) ;
213
+ }
214
+
185
215
this . _viewportSubscription . unsubscribe ( ) ;
186
216
this . _componentDestroyed = true ;
187
217
this . _destroyPanel ( ) ;
@@ -386,7 +416,9 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
386
416
}
387
417
388
418
_handleFocus ( ) : void {
389
- if ( this . _canOpen ( ) ) {
419
+ if ( ! this . _canOpenOnNextFocus ) {
420
+ this . _canOpenOnNextFocus = true ;
421
+ } else if ( this . _canOpen ( ) ) {
390
422
this . _previousValue = this . _element . nativeElement . value ;
391
423
this . _attachOverlay ( ) ;
392
424
this . _floatLabel ( true ) ;
@@ -633,5 +665,4 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
633
665
const element : HTMLInputElement = this . _element . nativeElement ;
634
666
return ! element . readOnly && ! element . disabled && ! this . _autocompleteDisabled ;
635
667
}
636
-
637
668
}
0 commit comments