From dec91ce08f6a4ceab19dbf3455003ad26c533436 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 12 Apr 2018 22:03:20 +0200 Subject: [PATCH] fix(button-toggle): selected value not being maintained when changing value while toggles are being swapped out (#10707) Fixes a regression that caused the button toggle group not maintaining the selected state if the selected value and the set of button toggles are swapped out at the same time. Fixes #10690. --- src/lib/button-toggle/button-toggle.spec.ts | 16 ++++++++++++++++ src/lib/button-toggle/button-toggle.ts | 21 +++++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lib/button-toggle/button-toggle.spec.ts b/src/lib/button-toggle/button-toggle.spec.ts index 657a548b3a5..4e45385f230 100644 --- a/src/lib/button-toggle/button-toggle.spec.ts +++ b/src/lib/button-toggle/button-toggle.spec.ts @@ -677,6 +677,22 @@ describe('MatButtonToggle without forms', () => { expect(fixture.componentInstance.toggleGroup.value).toBe('Two'); expect(fixture.componentInstance.toggles.toArray()[1].checked).toBe(true); }); + + it('should maintain the selected state when the value and toggles are swapped out at ' + + 'the same time', () => { + const fixture = TestBed.createComponent(RepeatedButtonTogglesWithPreselectedValue); + fixture.detectChanges(); + + expect(fixture.componentInstance.toggleGroup.value).toBe('Two'); + expect(fixture.componentInstance.toggles.toArray()[1].checked).toBe(true); + + fixture.componentInstance.possibleValues = ['Five', 'Six', 'Seven']; + fixture.componentInstance.value = 'Seven'; + fixture.detectChanges(); + + expect(fixture.componentInstance.toggleGroup.value).toBe('Seven'); + expect(fixture.componentInstance.toggles.toArray()[2].checked).toBe(true); + }); }); @Component({ diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index 013df249f6b..a5c0b1c2ea8 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -95,10 +95,12 @@ export class MatButtonToggleGroup extends _MatButtonToggleGroupMixinBase impleme private _selectionModel: SelectionModel; /** - * Used for storing a value temporarily, if it is assigned - * before the button toggles are initialized. + * Reference to the raw value that the consumer tried to assign. The real + * value will exaclude any values from this one that don't correspond to a + * toggle. Useful for the cases where the value is assigned before the toggles + * have been initialized or at the same that they're being swapped out. */ - private _tempValue: any; + private _rawValue: any; /** * The method to be called in order to update ngModel. @@ -181,7 +183,6 @@ export class MatButtonToggleGroup extends _MatButtonToggleGroupMixinBase impleme ngAfterContentInit() { this._selectionModel.select(...this._buttonToggles.filter(toggle => toggle.checked)); - this._tempValue = undefined; } /** @@ -257,22 +258,22 @@ export class MatButtonToggleGroup extends _MatButtonToggleGroupMixinBase impleme /** Determines whether a button toggle should be checked on init. */ _isPrechecked(toggle: MatButtonToggle) { - if (typeof this._tempValue === 'undefined') { + if (typeof this._rawValue === 'undefined') { return false; } - if (this.multiple && Array.isArray(this._tempValue)) { - return !!this._tempValue.find(value => toggle.value != null && value === toggle.value); + if (this.multiple && Array.isArray(this._rawValue)) { + return !!this._rawValue.find(value => toggle.value != null && value === toggle.value); } - return toggle.value === this._tempValue; + return toggle.value === this._rawValue; } /** Updates the selection state of the toggles in the group based on a value. */ private _setSelectionByValue(value: any|any[]) { - // If the toggles haven't been initialized yet, save the value for later. + this._rawValue = value; + if (!this._buttonToggles) { - this._tempValue = value; return; }