Skip to content

Commit a878e84

Browse files
committed
fix(material/form-field): error text fix
fixed issue where certain screen reader and browser pairings do not recognize mat-error being inserted into the DOM, changed it to where visibility is changing on the wrapper rather than adding and removing the hint and error wrappers. the changing of visibility should be recognized by all browser and screen reader pairings Fixes angular#29616
1 parent fead293 commit a878e84

File tree

3 files changed

+68
-20
lines changed

3 files changed

+68
-20
lines changed

src/material/form-field/form-field.html

+17-20
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,22 @@
9999
class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
100100
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
101101
>
102-
@switch (_getDisplayedMessages()) {
103-
@case ('error') {
104-
<div
105-
class="mat-mdc-form-field-error-wrapper"
106-
[@transitionMessages]="_subscriptAnimationState"
107-
>
108-
<ng-content select="mat-error, [matError]"></ng-content>
109-
</div>
110-
}
111-
112-
@case ('hint') {
113-
<div class="mat-mdc-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
114-
@if (hintLabel) {
115-
<mat-hint [id]="_hintLabelId">{{hintLabel}}</mat-hint>
116-
}
117-
<ng-content select="mat-hint:not([align='end'])"></ng-content>
118-
<div class="mat-mdc-form-field-hint-spacer"></div>
119-
<ng-content select="mat-hint[align='end']"></ng-content>
120-
</div>
102+
<div
103+
class="mat-mdc-form-field-error-wrapper mat-mdc-form-field-error-wrapper--hidden"
104+
[@transitionMessages]="_subscriptAnimationState"
105+
>
106+
<ng-content select="mat-error, [matError]"></ng-content>
107+
</div>
108+
109+
<div
110+
class="mat-mdc-form-field-hint-wrapper mat-mdc-form-field-hint-wrapper--hidden"
111+
[@transitionMessages]="_subscriptAnimationState"
112+
>
113+
@if (hintLabel) {
114+
<mat-hint [id]="_hintLabelId">{{hintLabel}}</mat-hint>
121115
}
122-
}
116+
<ng-content select="mat-hint:not([align='end'])"></ng-content>
117+
<div class="mat-mdc-form-field-hint-spacer"></div>
118+
<ng-content select="mat-hint[align='end']"></ng-content>
119+
</div>
123120
</div>

src/material/form-field/form-field.scss

+8
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,11 @@ $_icon-prefix-infix-padding: 4px;
218218
.mdc-notched-outline--upgraded .mdc-floating-label--float-above {
219219
max-width: calc(100% * 4 / 3 + 1px);
220220
}
221+
222+
.mat-mdc-form-field-error-wrapper--hidden {
223+
visibility: hidden;
224+
}
225+
226+
.mat-mdc-form-field-hint-wrapper--hidden {
227+
visibility: hidden;
228+
}

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

+43
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ export class MatFormField
437437
this._stateChanges = control.stateChanges.subscribe(() => {
438438
this._updateFocusState();
439439
this._syncDescribedByIds();
440+
this._showOrHideSubscript();
440441
this._changeDetectorRef.markForCheck();
441442
});
442443

@@ -478,17 +479,20 @@ export class MatFormField
478479
// Re-validate when the number of hints changes.
479480
this._hintChildren.changes.subscribe(() => {
480481
this._processHints();
482+
this._showOrHideSubscript();
481483
this._changeDetectorRef.markForCheck();
482484
});
483485

484486
// Update the aria-described by when the number of errors changes.
485487
this._errorChildren.changes.subscribe(() => {
486488
this._syncDescribedByIds();
489+
this._showOrHideSubscript();
487490
this._changeDetectorRef.markForCheck();
488491
});
489492

490493
// Initial mat-hint validation and subscript describedByIds sync.
491494
this._validateHints();
495+
this._showOrHideSubscript();
492496
this._syncDescribedByIds();
493497
}
494498

@@ -682,6 +686,45 @@ export class MatFormField
682686
}
683687
}
684688

689+
/**
690+
* Solves https://github.com/angular/components/issues/29616
691+
* Issues with certain browser and screen reader pairings not able to announce mat-error
692+
* when it's added to the DOM rather than changing the visibility of the hint/error wrappers.
693+
* Changing visibility instead of adding the div wrappers works for all browsers and sreen
694+
* readers.
695+
*
696+
* If there is an 'error' or 'hint' message being returned, remove visibility: hidden
697+
* style class and show error or hint section of code. If no 'error' or 'hint' messages are
698+
* being returned and no error children showing in query list, add visibility: hidden
699+
* style class back to error wrapper.
700+
*/
701+
private _showOrHideSubscript() {
702+
switch (this._getDisplayedMessages()) {
703+
case 'error': {
704+
console.log(this._elementRef.nativeElement.children[1].children[0].classList);
705+
this._elementRef.nativeElement.children[1].children[0].classList.remove(
706+
'mat-mdc-form-field-error-wrapper--hidden',
707+
);
708+
console.log(this._elementRef.nativeElement.children[1].children[0].classList);
709+
break;
710+
}
711+
case 'hint': {
712+
console.log(this._elementRef.nativeElement.children[1].children[1].classList);
713+
this._elementRef.nativeElement.children[1].children[1].classList.remove(
714+
'mat-mdc-form-field-hint-wrapper--hidden',
715+
);
716+
console.log(this._elementRef.nativeElement.children[1].children[1].classList);
717+
break;
718+
}
719+
}
720+
721+
if (!this._errorChildren || this._errorChildren.length === 0 || !this._control.errorState) {
722+
this._elementRef.nativeElement.children[1].children[0].classList.add(
723+
'mat-mdc-form-field-error-wrapper--hidden',
724+
);
725+
}
726+
}
727+
685728
/**
686729
* Updates the horizontal offset of the label in the outline appearance. In the outline
687730
* appearance, the notched-outline and label are not relative to the infix container because

0 commit comments

Comments
 (0)