diff --git a/src/material-experimental/mdc-select/select.spec.ts b/src/material-experimental/mdc-select/select.spec.ts index 06ec2d09ee67..1f89790daea9 100644 --- a/src/material-experimental/mdc-select/select.spec.ts +++ b/src/material-experimental/mdc-select/select.spec.ts @@ -42,6 +42,7 @@ import { } from '@angular/core/testing'; import { ControlValueAccessor, + FormBuilder, FormControl, FormGroup, FormGroupDirective, @@ -123,6 +124,7 @@ describe('MDC-based MatSelect', () => { SelectWithGroupsAndNgContainer, SelectWithFormFieldLabel, SelectWithChangeEvent, + SelectInsideDynamicFormGroup, ]); }), ); @@ -2193,6 +2195,23 @@ describe('MDC-based MatSelect', () => { .withContext(`Expected select panelOpen property to become true.`) .toBe(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); + fixture.detectChanges(); + const instance = fixture.componentInstance; + + expect(instance.select.disabled).toBe(false); + + instance.assignGroup(true); + fixture.detectChanges(); + + expect(instance.select.disabled).toBe(true); + }), + ); }); describe('keyboard scrolling', () => { @@ -5036,3 +5055,29 @@ class SelectWithResetOptionAndFormControl { `, }) class SelectInNgContainer {} + +@Component({ + template: ` +
+ `, +}) +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.spec.ts b/src/material/select/select.spec.ts index 4ba42d18b7d0..a0cd6a819e10 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -49,6 +49,7 @@ import { NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators, + FormBuilder, } from '@angular/forms'; import {ErrorStateMatcher, MatOption, MatOptionSelectionChange} from '@angular/material/core'; import { @@ -122,6 +123,7 @@ describe('MatSelect', () => { SelectWithGroupsAndNgContainer, SelectWithFormFieldLabel, SelectWithChangeEvent, + SelectInsideDynamicFormGroup, ]); }), ); @@ -2208,6 +2210,23 @@ describe('MatSelect', () => { .withContext(`Expected select panelOpen property to become true.`) .toBe(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); + fixture.detectChanges(); + const instance = fixture.componentInstance; + + expect(instance.select.disabled).toBe(false); + + instance.assignGroup(true); + fixture.detectChanges(); + + expect(instance.select.disabled).toBe(true); + }), + ); }); describe('animations', () => { @@ -6017,3 +6036,29 @@ class SelectWithResetOptionAndFormControl { `, }) class SelectInNgContainer {} + +@Component({ + template: ` + + `, +}) +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 ecd5e82b6ab8..b6444f4b7430 100644 --- a/src/material/select/select.ts +++ b/src/material/select/select.ts @@ -60,6 +60,7 @@ import { ViewEncapsulation, } from '@angular/core'; import { + AbstractControl, ControlValueAccessor, FormGroupDirective, NgControl, @@ -281,6 +282,12 @@ export abstract class _MatSelectBase