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 Dec 4, 2019
1 parent 49b6dbd commit 02e1c57
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 @@ -48,6 +48,7 @@ import {
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
Validators,
FormBuilder,
} from '@angular/forms';
import {
ErrorStateMatcher,
Expand Down Expand Up @@ -128,6 +129,7 @@ describe('MatSelect', () => {
SelectWithGroupsAndNgContainer,
SelectWithFormFieldLabel,
SelectWithChangeEvent,
SelectInsideDynamicFormGroup,
]);
}));

Expand Down Expand Up @@ -1903,6 +1905,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 @@ -5267,3 +5283,30 @@ class MultiSelectWithLotsOfOptions {
this.value = [];
}
}


@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 @@ -566,6 +566,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 02e1c57

Please sign in to comment.