Skip to content

Commit 9721022

Browse files
committed
fix(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 db4b0cd commit 9721022

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

src/material/autocomplete/autocomplete-trigger.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,11 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, AfterViewIn
350350

351351
/** Stream of clicks outside of the autocomplete panel. */
352352
private _getOutsideClickStream(): Observable<any> {
353+
// Use capturing so we can close even if propagation is stopped.
354+
const eventOptions = {capture: true};
353355
return merge(
354-
fromEvent(this._document, 'click') as Observable<MouseEvent>,
355-
fromEvent(this._document, 'touchend') as Observable<TouchEvent>)
356+
fromEvent(this._document, 'click', eventOptions) as Observable<MouseEvent>,
357+
fromEvent(this._document, 'touchend', eventOptions) as Observable<TouchEvent>)
356358
.pipe(filter(event => {
357359
// If we're in the Shadow DOM, the event target will be the shadow root, so we have to
358360
// 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();
@@ -2631,6 +2645,8 @@ const SIMPLE_AUTOCOMPLETE_TEMPLATE = `
26312645
<span>{{ state.code }}: {{ state.name }}</span>
26322646
</mat-option>
26332647
</mat-autocomplete>
2648+
2649+
<button class="stop-propagation" (click)="$event.stopPropagation()">Click me</button>
26342650
`;
26352651

26362652
@Component({template: SIMPLE_AUTOCOMPLETE_TEMPLATE})

0 commit comments

Comments
 (0)