File tree Expand file tree Collapse file tree 3 files changed +44
-1
lines changed
material-experimental/mdc-autocomplete Expand file tree Collapse file tree 3 files changed +44
-1
lines changed Original file line number Diff line number Diff line change 99 dispatchEvent ,
1010 dispatchFakeEvent ,
1111 dispatchKeyboardEvent ,
12+ dispatchMouseEvent ,
1213 MockNgZone ,
1314 typeInElement ,
1415} from '../../cdk/testing/private' ;
@@ -1261,6 +1262,24 @@ describe('MDC-based MatAutocomplete', () => {
12611262 . toBeFalsy ( 'Expected panel to be removed.' ) ;
12621263 } ) ) ;
12631264
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+
12641283 it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
12651284 const trigger = fixture . componentInstance . trigger ;
12661285
Original file line number Diff line number Diff line change @@ -336,6 +336,11 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
336336 const customOrigin = this . connectedTo ? this . connectedTo . elementRef . nativeElement : null ;
337337
338338 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 &&
339344 ( ! formField || ! formField . contains ( clickTarget ) ) &&
340345 ( ! customOrigin || ! customOrigin . contains ( clickTarget ) ) &&
341346 ( ! ! this . _overlayRef && ! this . _overlayRef . overlayElement . contains ( clickTarget ) ) ;
Original file line number Diff line number Diff line change @@ -11,7 +11,8 @@ import {
1111 dispatchFakeEvent ,
1212 dispatchKeyboardEvent ,
1313 typeInElement ,
14- } from '../../cdk/testing/private' ;
14+ dispatchMouseEvent ,
15+ } from '@angular/cdk/testing/private' ;
1516import {
1617 ChangeDetectionStrategy ,
1718 Component ,
@@ -1250,6 +1251,24 @@ describe('MatAutocomplete', () => {
12501251 . toBeFalsy ( 'Expected panel to be removed.' ) ;
12511252 } ) ) ;
12521253
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+
12531272 it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
12541273 const trigger = fixture . componentInstance . trigger ;
12551274
You can’t perform that action at this time.
0 commit comments