File tree 3 files changed +44
-1
lines changed
material-experimental/mdc-autocomplete
3 files changed +44
-1
lines changed Original file line number Diff line number Diff line change 9
9
dispatchEvent ,
10
10
dispatchFakeEvent ,
11
11
dispatchKeyboardEvent ,
12
+ dispatchMouseEvent ,
12
13
MockNgZone ,
13
14
typeInElement ,
14
15
} from '../../cdk/testing/private' ;
@@ -1261,6 +1262,24 @@ describe('MDC-based MatAutocomplete', () => {
1261
1262
. toBeFalsy ( 'Expected panel to be removed.' ) ;
1262
1263
} ) ) ;
1263
1264
1265
+ it ( 'should not close when a click event occurs on the outside while the panel has focus' ,
1266
+ fakeAsync ( ( ) => {
1267
+ const trigger = fixture . componentInstance . trigger ;
1268
+
1269
+ input . focus ( ) ;
1270
+ flush ( ) ;
1271
+ fixture . detectChanges ( ) ;
1272
+
1273
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to be focused.' ) ;
1274
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
1275
+
1276
+ dispatchMouseEvent ( document . body , 'click' ) ;
1277
+ fixture . detectChanges ( ) ;
1278
+
1279
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to continue to be focused.' ) ;
1280
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to stay open.' ) ;
1281
+ } ) ) ;
1282
+
1264
1283
it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
1265
1284
const trigger = fixture . componentInstance . trigger ;
1266
1285
Original file line number Diff line number Diff line change @@ -336,6 +336,11 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
336
336
const customOrigin = this . connectedTo ? this . connectedTo . elementRef . nativeElement : null ;
337
337
338
338
return this . _overlayAttached && clickTarget !== this . _element . nativeElement &&
339
+ // Normally focus moves inside `mousedown` so this condition will almost always be
340
+ // true. Its main purpose is to handle the case where the input is focused from an
341
+ // outside click which propagates up to the `body` listener within the same sequence
342
+ // and causes the panel to close immediately (see #3106).
343
+ this . _document . activeElement !== this . _element . nativeElement &&
339
344
( ! formField || ! formField . contains ( clickTarget ) ) &&
340
345
( ! customOrigin || ! customOrigin . contains ( clickTarget ) ) &&
341
346
( ! ! this . _overlayRef && ! this . _overlayRef . overlayElement . contains ( clickTarget ) ) ;
Original file line number Diff line number Diff line change @@ -11,7 +11,8 @@ import {
11
11
dispatchFakeEvent ,
12
12
dispatchKeyboardEvent ,
13
13
typeInElement ,
14
- } from '../../cdk/testing/private' ;
14
+ dispatchMouseEvent ,
15
+ } from '@angular/cdk/testing/private' ;
15
16
import {
16
17
ChangeDetectionStrategy ,
17
18
Component ,
@@ -1250,6 +1251,24 @@ describe('MatAutocomplete', () => {
1250
1251
. toBeFalsy ( 'Expected panel to be removed.' ) ;
1251
1252
} ) ) ;
1252
1253
1254
+ it ( 'should not close when a click event occurs on the outside while the panel has focus' ,
1255
+ fakeAsync ( ( ) => {
1256
+ const trigger = fixture . componentInstance . trigger ;
1257
+
1258
+ input . focus ( ) ;
1259
+ flush ( ) ;
1260
+ fixture . detectChanges ( ) ;
1261
+
1262
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to be focused.' ) ;
1263
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
1264
+
1265
+ dispatchMouseEvent ( document . body , 'click' ) ;
1266
+ fixture . detectChanges ( ) ;
1267
+
1268
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to continue to be focused.' ) ;
1269
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to stay open.' ) ;
1270
+ } ) ) ;
1271
+
1253
1272
it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
1254
1273
const trigger = fixture . componentInstance . trigger ;
1255
1274
You can’t perform that action at this time.
0 commit comments