Skip to content

Commit 5fa2d4c

Browse files
committed
fix(material/autocomplete): not closing when clicking outside while propagation is stopped
Fixes the autocomplete panel not closing if the user clicks outside on an element that stops propagation of the `click` event (e.g. a `mat-chip`). Fixes #17352.
1 parent 71b7b15 commit 5fa2d4c

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

src/material-experimental/mdc-autocomplete/autocomplete.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,20 @@ describe('MDC-based MatAutocomplete', () => {
187187
.toEqual('', `Expected clicking outside the panel to close the panel.`);
188188
}));
189189

190+
it('should close the panel when clicking away and propagation is stopped', fakeAsync(() => {
191+
const trigger = fixture.componentInstance.trigger;
192+
dispatchFakeEvent(input, 'focusin');
193+
fixture.detectChanges();
194+
zone.simulateZoneExit();
195+
196+
expect(trigger.panelOpen).toBe(true, 'Expected panel to be open.');
197+
198+
fixture.nativeElement.querySelector('.stop-propagation').click();
199+
fixture.detectChanges();
200+
201+
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
202+
}));
203+
190204
it('should close the panel when the user taps away on a touch device', fakeAsync(() => {
191205
dispatchFakeEvent(input, 'focus');
192206
fixture.detectChanges();
@@ -2748,6 +2762,8 @@ const SIMPLE_AUTOCOMPLETE_TEMPLATE = `
27482762
<span>{{ state.code }}: {{ state.name }}</span>
27492763
</mat-option>
27502764
</mat-autocomplete>
2765+
2766+
<button class="stop-propagation" (click)="$event.stopPropagation()">Click me</button>
27512767
`;
27522768

27532769
@Component({template: SIMPLE_AUTOCOMPLETE_TEMPLATE})

src/material/autocomplete/autocomplete-trigger.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,11 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
347347

348348
/** Stream of clicks outside of the autocomplete panel. */
349349
private _getOutsideClickStream(): Observable<any> {
350+
// Use capturing so we can close even if propagation is stopped.
351+
const eventOptions = {capture: true};
350352
return merge(
351-
fromEvent(this._document, 'click') as Observable<MouseEvent>,
352-
fromEvent(this._document, 'touchend') as Observable<TouchEvent>)
353+
fromEvent(this._document, 'click', eventOptions) as Observable<MouseEvent>,
354+
fromEvent(this._document, 'touchend', eventOptions) as Observable<TouchEvent>)
353355
.pipe(filter(event => {
354356
// If we're in the Shadow DOM, the event target will be the shadow root, so we have to
355357
// fall back to check the first element in the path of the click event.

src/material/autocomplete/autocomplete.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ describe('MatAutocomplete', () => {
188188
.toEqual('', `Expected clicking outside the panel to close the panel.`);
189189
}));
190190

191+
it('should close the panel when clicking away and propagation is stopped', fakeAsync(() => {
192+
const trigger = fixture.componentInstance.trigger;
193+
dispatchFakeEvent(input, 'focusin');
194+
fixture.detectChanges();
195+
zone.simulateZoneExit();
196+
197+
expect(trigger.panelOpen).toBe(true, 'Expected panel to be open.');
198+
199+
fixture.nativeElement.querySelector('.stop-propagation').click();
200+
fixture.detectChanges();
201+
202+
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
203+
}));
204+
191205
it('should close the panel when the user taps away on a touch device', fakeAsync(() => {
192206
dispatchFakeEvent(input, 'focus');
193207
fixture.detectChanges();
@@ -2752,6 +2766,8 @@ const SIMPLE_AUTOCOMPLETE_TEMPLATE = `
27522766
<span>{{ state.code }}: {{ state.name }}</span>
27532767
</mat-option>
27542768
</mat-autocomplete>
2769+
2770+
<button class="stop-propagation" (click)="$event.stopPropagation()">Click me</button>
27552771
`;
27562772

27572773
@Component({template: SIMPLE_AUTOCOMPLETE_TEMPLATE})

0 commit comments

Comments
 (0)