File tree 3 files changed +43
-0
lines changed
material-experimental/mdc-autocomplete
3 files changed +43
-0
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 '@angular/cdk/testing/private' ;
@@ -1241,6 +1242,24 @@ describe('MDC-based MatAutocomplete', () => {
1241
1242
. toBeFalsy ( 'Expected panel to be removed.' ) ;
1242
1243
} ) ) ;
1243
1244
1245
+ it ( 'should not close when a click event occurs on the outside while the panel has focus' ,
1246
+ fakeAsync ( ( ) => {
1247
+ const trigger = fixture . componentInstance . trigger ;
1248
+
1249
+ input . focus ( ) ;
1250
+ flush ( ) ;
1251
+ fixture . detectChanges ( ) ;
1252
+
1253
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to be focused.' ) ;
1254
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
1255
+
1256
+ dispatchMouseEvent ( document . body , 'click' ) ;
1257
+ fixture . detectChanges ( ) ;
1258
+
1259
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to continue to be focused.' ) ;
1260
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to stay open.' ) ;
1261
+ } ) ) ;
1262
+
1244
1263
it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
1245
1264
const trigger = fixture . componentInstance . trigger ;
1246
1265
Original file line number Diff line number Diff line change @@ -360,6 +360,11 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
360
360
const customOrigin = this . connectedTo ? this . connectedTo . elementRef . nativeElement : null ;
361
361
362
362
return this . _overlayAttached && clickTarget !== this . _element . nativeElement &&
363
+ // Normally focus moves inside `mousedown` so this condition will almost always be
364
+ // true. Its main purpose is to handle the case where the input is focused from an
365
+ // outside click which propagates up to the `body` listener within the same sequence
366
+ // and causes the panel to close immediately (see #3106).
367
+ this . _document . activeElement !== this . _element . nativeElement &&
363
368
( ! formField || ! formField . contains ( clickTarget ) ) &&
364
369
( ! customOrigin || ! customOrigin . contains ( clickTarget ) ) &&
365
370
( ! ! this . _overlayRef && ! this . _overlayRef . overlayElement . contains ( clickTarget ) ) ;
Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ import {
11
11
dispatchFakeEvent ,
12
12
dispatchKeyboardEvent ,
13
13
typeInElement ,
14
+ dispatchMouseEvent ,
14
15
} from '@angular/cdk/testing/private' ;
15
16
import {
16
17
ChangeDetectionStrategy ,
@@ -1238,6 +1239,24 @@ describe('MatAutocomplete', () => {
1238
1239
. toBeFalsy ( 'Expected panel to be removed.' ) ;
1239
1240
} ) ) ;
1240
1241
1242
+ it ( 'should not close when a click event occurs on the outside while the panel has focus' ,
1243
+ fakeAsync ( ( ) => {
1244
+ const trigger = fixture . componentInstance . trigger ;
1245
+
1246
+ input . focus ( ) ;
1247
+ flush ( ) ;
1248
+ fixture . detectChanges ( ) ;
1249
+
1250
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to be focused.' ) ;
1251
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
1252
+
1253
+ dispatchMouseEvent ( document . body , 'click' ) ;
1254
+ fixture . detectChanges ( ) ;
1255
+
1256
+ expect ( document . activeElement ) . toBe ( input , 'Expected input to continue to be focused.' ) ;
1257
+ expect ( trigger . panelOpen ) . toBe ( true , 'Expected panel to stay open.' ) ;
1258
+ } ) ) ;
1259
+
1241
1260
it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
1242
1261
const trigger = fixture . componentInstance . trigger ;
1243
1262
You can’t perform that action at this time.
0 commit comments