File tree Expand file tree Collapse file tree 3 files changed +43
-0
lines changed
material-experimental/mdc-autocomplete Expand file tree Collapse file tree 3 files changed +43
-0
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 '@angular/cdk/testing/private' ;
@@ -1241,6 +1242,24 @@ describe('MDC-based MatAutocomplete', () => {
12411242 . toBeFalsy ( 'Expected panel to be removed.' ) ;
12421243 } ) ) ;
12431244
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+
12441263 it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
12451264 const trigger = fixture . componentInstance . trigger ;
12461265
Original file line number Diff line number Diff line change @@ -360,6 +360,11 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
360360 const customOrigin = this . connectedTo ? this . connectedTo . elementRef . nativeElement : null ;
361361
362362 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 &&
363368 ( ! formField || ! formField . contains ( clickTarget ) ) &&
364369 ( ! customOrigin || ! customOrigin . contains ( clickTarget ) ) &&
365370 ( ! ! this . _overlayRef && ! this . _overlayRef . overlayElement . contains ( clickTarget ) ) ;
Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ import {
1111 dispatchFakeEvent ,
1212 dispatchKeyboardEvent ,
1313 typeInElement ,
14+ dispatchMouseEvent ,
1415} from '@angular/cdk/testing/private' ;
1516import {
1617 ChangeDetectionStrategy ,
@@ -1238,6 +1239,24 @@ describe('MatAutocomplete', () => {
12381239 . toBeFalsy ( 'Expected panel to be removed.' ) ;
12391240 } ) ) ;
12401241
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+
12411260 it ( 'should reset the active option when closing with the escape key' , fakeAsync ( ( ) => {
12421261 const trigger = fixture . componentInstance . trigger ;
12431262
You can’t perform that action at this time.
0 commit comments