Skip to content

Commit 0d20156

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 aa7dc00 commit 0d20156

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

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

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

204+
it('should close the panel when clicking away and propagation is stopped', fakeAsync(() => {
205+
const trigger = fixture.componentInstance.trigger;
206+
dispatchFakeEvent(input, 'focusin');
207+
fixture.detectChanges();
208+
zone.simulateZoneExit();
209+
210+
expect(trigger.panelOpen).toBe(true, 'Expected panel to be open.');
211+
212+
fixture.nativeElement.querySelector('.stop-propagation').click();
213+
fixture.detectChanges();
214+
215+
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
216+
}));
217+
204218
it('should close the panel when the user taps away on a touch device', fakeAsync(() => {
205219
dispatchFakeEvent(input, 'focus');
206220
fixture.detectChanges();
@@ -2783,6 +2797,8 @@ const SIMPLE_AUTOCOMPLETE_TEMPLATE = `
27832797
<span>{{ state.code }}: {{ state.name }}</span>
27842798
</mat-option>
27852799
</mat-autocomplete>
2800+
2801+
<button class="stop-propagation" (click)="$event.stopPropagation()">Click me</button>
27862802
`;
27872803

27882804
@Component({template: SIMPLE_AUTOCOMPLETE_TEMPLATE})

src/material/autocomplete/autocomplete-trigger.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,12 @@ 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, 'auxclick') as Observable<MouseEvent>,
353-
fromEvent(this._document, 'touchend') as Observable<TouchEvent>)
353+
fromEvent(this._document, 'click', eventOptions) as Observable<MouseEvent>,
354+
fromEvent(this._document, 'auxclick', eventOptions) as Observable<MouseEvent>,
355+
fromEvent(this._document, 'touchend', eventOptions) as Observable<TouchEvent>)
354356
.pipe(filter(event => {
355357
// If we're in the Shadow DOM, the event target will be the shadow root, so we have to
356358
// fall back to check the first element in the path of the click event.

src/material/autocomplete/autocomplete.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ describe('MatAutocomplete', () => {
198198
.toBe(false, `Expected clicking outside the panel to set its state to closed.`);
199199
expect(overlayContainerElement.textContent)
200200
.toEqual('', `Expected clicking outside the panel to close the panel.`);
201+
202+
}));
203+
204+
it('should close the panel when clicking away and propagation is stopped', fakeAsync(() => {
205+
const trigger = fixture.componentInstance.trigger;
206+
dispatchFakeEvent(input, 'focusin');
207+
fixture.detectChanges();
208+
zone.simulateZoneExit();
209+
210+
expect(trigger.panelOpen).toBe(true, 'Expected panel to be open.');
211+
212+
fixture.nativeElement.querySelector('.stop-propagation').click();
213+
fixture.detectChanges();
214+
215+
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
201216
}));
202217

203218
it('should close the panel when the user taps away on a touch device', fakeAsync(() => {
@@ -2780,6 +2795,8 @@ const SIMPLE_AUTOCOMPLETE_TEMPLATE = `
27802795
<span>{{ state.code }}: {{ state.name }}</span>
27812796
</mat-option>
27822797
</mat-autocomplete>
2798+
2799+
<button class="stop-propagation" (click)="$event.stopPropagation()">Click me</button>
27832800
`;
27842801

27852802
@Component({template: SIMPLE_AUTOCOMPLETE_TEMPLATE})

0 commit comments

Comments
 (0)