Skip to content

Commit f43e3e8

Browse files
devversionjelbourn
authored andcommitted
fix(material-experimental/mdc-form-field): ensure validity styling is not reset by foundation (#18266)
Currently, whenever the abstract form-field control turns invalid, the text-field foundation does not know about the validity change. Since it refreshes the validity upon focus/blur, it could end up accidentally removing the invalid class. We fix this, by ensuring that the foundation shares the validity state with the one from the form-field control.
1 parent e37b5e5 commit f43e3e8

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/material-experimental/mdc-form-field/form-field.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ export class MatFormField implements AfterViewInit, OnDestroy, AfterContentCheck
283283
get: () => this._shouldLabelFloat(),
284284
});
285285

286+
// By default, the foundation determines the validity of the text-field from the
287+
// specified native input. Since we don't pass a native input to the foundation because
288+
// abstract form controls are not necessarily consisting of an input, we handle the
289+
// text-field validity through the abstract form-field control state.
290+
this._foundation.isValid = () => !this._control.errorState;
291+
286292
// Initial focus state sync. This happens rarely, but we want to account for
287293
// it in case the form-field control has "focused" set to true on init.
288294
this._updateFocusState();

src/material-experimental/mdc-input/input.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,21 @@ describe('MatMdcInput with forms', () => {
830830
.toBe('true', 'Expected aria-invalid to be set to "true".');
831831
}));
832832

833+
it('should not reset text-field validity if focus changes for an invalid input',
834+
fakeAsync(() => {
835+
// Mark the control as touched, so that the form-field displays as invalid.
836+
testComponent.formControl.markAsTouched();
837+
fixture.detectChanges();
838+
flush();
839+
840+
const wrapperEl = containerEl.querySelector('.mdc-text-field')!;
841+
expect(wrapperEl.classList).toContain('mdc-text-field--invalid');
842+
843+
dispatchFakeEvent(inputEl, 'focus');
844+
dispatchFakeEvent(inputEl, 'blur');
845+
expect(wrapperEl.classList).toContain('mdc-text-field--invalid');
846+
}));
847+
833848
it('should display an error message when the parent form is submitted', fakeAsync(() => {
834849
expect(testComponent.form.submitted).toBe(false, 'Expected form not to have been submitted');
835850
expect(testComponent.formControl.invalid).toBe(true, 'Expected form control to be invalid');

0 commit comments

Comments
 (0)