Skip to content

Commit 547357a

Browse files
authored
fix(material/form-field): not visually disabled if form control is disabled without emitting an event (#26088)
Fixes that the form field wasn't visually disabled if the consumer disables it using `emitEvents: false`. Fixes #26057.
1 parent 3c03ad4 commit 547357a

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

src/material/input/input.spec.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ describe('MatMdcInput with forms', () => {
11881188

11891189
describe('custom error behavior', () => {
11901190
it('should display an error message when a custom error matcher returns true', fakeAsync(() => {
1191-
let fixture = createComponent(MatInputWithCustomErrorStateMatcher);
1191+
let fixture = createComponent(InputInFormGroup);
11921192
fixture.detectChanges();
11931193

11941194
let component = fixture.componentInstance;
@@ -1356,6 +1356,18 @@ describe('MatMdcInput with forms', () => {
13561356

13571357
expect(notch.style.width).toBeTruthy();
13581358
}));
1359+
1360+
it('should mark the form field as disabled when a group is disabled with emitEvent: false', fakeAsync(() => {
1361+
const fixture = createComponent(InputInFormGroup);
1362+
fixture.detectChanges();
1363+
1364+
const mdcTextField = fixture.nativeElement.querySelector('.mdc-text-field');
1365+
expect(mdcTextField.classList).not.toContain('mdc-text-field--disabled');
1366+
1367+
fixture.componentInstance.formGroup.disable({emitEvent: false});
1368+
fixture.detectChanges();
1369+
expect(mdcTextField.classList).toContain('mdc-text-field--disabled');
1370+
}));
13591371
});
13601372

13611373
describe('MatFormField default options', () => {
@@ -1793,7 +1805,7 @@ class MatInputWithFormErrorMessages {
17931805
</form>
17941806
`,
17951807
})
1796-
class MatInputWithCustomErrorStateMatcher {
1808+
class InputInFormGroup {
17971809
formGroup = new FormGroup({
17981810
name: new FormControl('', [Validators.required, Validators.pattern(/valid value/)]),
17991811
});

src/material/input/input.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,6 @@ export class MatInput
160160
*/
161161
@Input()
162162
get disabled(): boolean {
163-
if (this.ngControl && this.ngControl.disabled !== null) {
164-
return this.ngControl.disabled;
165-
}
166163
return this._disabled;
167164
}
168165
set disabled(value: BooleanInput) {
@@ -356,6 +353,15 @@ export class MatInput
356353
// error triggers that we can't subscribe to (e.g. parent form submissions). This means
357354
// that whatever logic is in here has to be super lean or we risk destroying the performance.
358355
this.updateErrorState();
356+
357+
// Since the input isn't a `ControlValueAccessor`, we don't have a good way of knowing when
358+
// the disabled state has changed. We can't use the `ngControl.statusChanges`, because it
359+
// won't fire if the input is disabled with `emitEvents = false`, despite the input becoming
360+
// disabled.
361+
if (this.ngControl.disabled !== null && this.ngControl.disabled !== this.disabled) {
362+
this.disabled = this.ngControl.disabled;
363+
this.stateChanges.next();
364+
}
359365
}
360366

361367
// We need to dirty-check the native element's value, because there are some cases where

0 commit comments

Comments
 (0)