Skip to content

Commit

Permalink
fix(select): disabled state out of sync when swapping form group with…
Browse files Browse the repository at this point in the history
… 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 angular#17860.
  • Loading branch information
crisbeto committed Aug 21, 2020
1 parent f0c7a25 commit cf377fe
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/material/select/select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
Validators,
FormBuilder,
} from '@angular/forms';
import {
ErrorStateMatcher,
Expand Down Expand Up @@ -131,6 +132,7 @@ describe('MatSelect', () => {
SelectWithGroupsAndNgContainer,
SelectWithFormFieldLabel,
SelectWithChangeEvent,
SelectInsideDynamicFormGroup,
]);
}));

Expand Down Expand Up @@ -1912,6 +1914,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', () => {
Expand Down Expand Up @@ -5430,3 +5446,30 @@ class SelectWithResetOptionAndFormControl {
@ViewChildren(MatOption) options: QueryList<MatOption>;
control = new FormControl();
}


@Component({
template: `
<form [formGroup]="form">
<mat-form-field>
<mat-select formControlName="control">
<mat-option value="1">One</mat-option>
</mat-select>
</mat-form-field>
</form>
`
})
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}
});
}
}
5 changes: 5 additions & 0 deletions src/material/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,11 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,

ngDoCheck() {
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();
}
}
Expand Down

0 comments on commit cf377fe

Please sign in to comment.