Skip to content

Commit 880e6d5

Browse files
crisbetommalerba
authored andcommitted
fix(autocomplete): error when closing destroyed panel (#5446)
Fixes an error that was being thrown when attempting to close the panel of an autocomplete that is inside a destroyed view. The issue is that `closePanel` can end up getting called multiple times in a row, which leads to an attempt to call `detectChanges` on a destroyed `ChangeDetectorRef`. Fixes #5413.
1 parent 372549c commit 880e6d5

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
170170

171171
/** Closes the autocomplete suggestion panel. */
172172
closePanel(): void {
173+
if (!this.panelOpen) {
174+
return;
175+
}
176+
173177
if (this._overlayRef && this._overlayRef.hasAttached()) {
174178
this._overlayRef.detach();
175179
this._closingActionsSubscription.unsubscribe();

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,17 +221,31 @@ describe('MdAutocomplete', () => {
221221
});
222222
}));
223223

224-
it('should close the panel programmatically', () => {
224+
it('should close the panel programmatically', async(() => {
225225
fixture.componentInstance.trigger.openPanel();
226226
fixture.detectChanges();
227227

228-
fixture.componentInstance.trigger.closePanel();
228+
fixture.whenStable().then(() => {
229+
fixture.componentInstance.trigger.closePanel();
230+
fixture.detectChanges();
231+
232+
fixture.whenStable().then(() => {
233+
expect(fixture.componentInstance.trigger.panelOpen)
234+
.toBe(false, `Expected closing programmatically to set the panel state to closed.`);
235+
expect(overlayContainerElement.textContent)
236+
.toEqual('', `Expected closing programmatically to close the panel.`);
237+
});
238+
});
239+
}));
240+
241+
it('should not throw when attempting to close the panel of a destroyed autocomplete', () => {
242+
const trigger = fixture.componentInstance.trigger;
243+
244+
trigger.openPanel();
229245
fixture.detectChanges();
246+
fixture.destroy();
230247

231-
expect(fixture.componentInstance.trigger.panelOpen)
232-
.toBe(false, `Expected closing programmatically to set the panel state to closed.`);
233-
expect(overlayContainerElement.textContent)
234-
.toEqual('', `Expected closing programmatically to close the panel.`);
248+
expect(() => trigger.closePanel()).not.toThrow();
235249
});
236250

237251
it('should hide the panel when the options list is empty', async(() => {

0 commit comments

Comments
 (0)