From a1fffb522dc7d3e7cecbbeb8172524b2f03da886 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 26 Nov 2020 18:47:15 +0100 Subject: [PATCH] fix(material/select): disabled state out of sync when swapping form group with a disabled one Fixes the disabled state of a `mat-select` falling out of sync with its form control if the control's group is swapped out with one that is disabled on init. Fixes #17860. --- src/material/select/select.spec.ts | 42 ++++++++++++++++++++++++++++++ src/material/select/select.ts | 5 ++++ 2 files changed, 47 insertions(+) diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts index 73ca9fd7b3c5..027bbefc6442 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -50,6 +50,7 @@ import { NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators, + FormBuilder, } from '@angular/forms'; import { ErrorStateMatcher, @@ -133,6 +134,7 @@ describe('MatSelect', () => { SelectWithGroupsAndNgContainer, SelectWithFormFieldLabel, SelectWithChangeEvent, + SelectInsideDynamicFormGroup, ]); })); @@ -1999,6 +2001,20 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select.panelOpen) .toBe(true, `Expected select panelOpen property to become true.`); })); + + it('should keep the disabled state in sync if the form group is swapped and ' + + 'disabled at the same time', fakeAsync(() => { + const fixture = TestBed.createComponent(SelectInsideDynamicFormGroup); + const instance = fixture.componentInstance; + fixture.detectChanges(); + + expect(instance.select.disabled).toBe(false); + + instance.assignGroup(true); + fixture.detectChanges(); + + expect(instance.select.disabled).toBe(true); + })); }); describe('animations', () => { @@ -5507,3 +5523,29 @@ class SelectWithResetOptionAndFormControl { ` }) class SelectInNgContainer {} + +@Component({ + template: ` +
+ + + One + + +
+ ` +}) +class SelectInsideDynamicFormGroup { + @ViewChild(MatSelect) select: MatSelect; + form: FormGroup; + + constructor(private _formBuilder: FormBuilder) { + this.assignGroup(false); + } + + assignGroup(isDisabled: boolean) { + this.form = this._formBuilder.group({ + control: {value: '', disabled: isDisabled} + }); + } +} diff --git a/src/material/select/select.ts b/src/material/select/select.ts index b9d3cef7f547..47bcccf15d6d 100644 --- a/src/material/select/select.ts +++ b/src/material/select/select.ts @@ -555,6 +555,11 @@ export abstract class _MatSelectBase extends _MatSelectMixinBase implements A } if (this.ngControl) { + // The disabled state might go out of sync if the form group is swapped out. See #17860. + if (this.ngControl.disabled !== this.disabled) { + this.disabled = !!this.ngControl.disabled; + } + this.updateErrorState(); } }