From 0250f7181e768693cf360b8e58b5958eb5188b96 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Mon, 24 Dec 2018 17:11:48 +0200 Subject: [PATCH] fix(button-toggle): remove references to selected toggle on destroy Currently when a button toggle is destroyed, we still keep a reference to it in the selection model which is leaky and causes the model value to be inaccurate. These changes remove the reference. --- src/lib/button-toggle/button-toggle.spec.ts | 20 +++++++++++++++++++- src/lib/button-toggle/button-toggle.ts | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib/button-toggle/button-toggle.spec.ts b/src/lib/button-toggle/button-toggle.spec.ts index 9a98d523802e..c67babee0980 100644 --- a/src/lib/button-toggle/button-toggle.spec.ts +++ b/src/lib/button-toggle/button-toggle.spec.ts @@ -416,6 +416,23 @@ describe('MatButtonToggle without forms', () => { expect(buttonToggleInstances.every(toggle => !toggle.checked)).toBe(true); }); + + it('should update the model if a selected toggle is removed', fakeAsync(() => { + expect(groupInstance.value).toBeFalsy(); + buttonToggleLabelElements[0].click(); + fixture.detectChanges(); + + expect(groupInstance.value).toBe('test1'); + expect(groupInstance.selected).toBe(buttonToggleInstances[0]); + + testComponent.renderFirstToggle = false; + fixture.detectChanges(); + tick(); + + expect(groupInstance.value).toBeFalsy(); + expect(groupInstance.selected).toBeFalsy(); + })); + }); describe('with initial value and change event', () => { @@ -787,7 +804,7 @@ describe('MatButtonToggle without forms', () => { - Test1 + Test1 Test2 Test3 @@ -797,6 +814,7 @@ class ButtonTogglesInsideButtonToggleGroup { isGroupDisabled: boolean = false; isVertical: boolean = false; groupValue: string; + renderFirstToggle = true; } @Component({ diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index c4b728bc9da3..0b42d51eb2ac 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -487,7 +487,15 @@ export class MatButtonToggle extends _MatButtonToggleMixinBase implements OnInit } ngOnDestroy() { + const group = this.buttonToggleGroup; + this._focusMonitor.stopMonitoring(this._elementRef); + + // Remove the toggle from the selection once it's destroyed. Needs to happen + // on the next tick in order to avoid "changed after checked" errors. + if (group && group._isSelected(this)) { + Promise.resolve().then(() => group._syncButtonToggle(this, false)); + } } /** Focuses the button. */