Skip to content

Commit

Permalink
fix(matarial/form-field): error text fix
Browse files Browse the repository at this point in the history
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
  • Loading branch information
DBowen33 committed Sep 11, 2024
1 parent fead293 commit e9228db
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 20 deletions.
37 changes: 17 additions & 20 deletions src/material/form-field/form-field.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,22 @@
class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
>
@switch (_getDisplayedMessages()) {
@case ('error') {
<div
class="mat-mdc-form-field-error-wrapper"
[@transitionMessages]="_subscriptAnimationState"
>
<ng-content select="mat-error, [matError]"></ng-content>
</div>
}

@case ('hint') {
<div class="mat-mdc-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
@if (hintLabel) {
<mat-hint [id]="_hintLabelId">{{hintLabel}}</mat-hint>
}
<ng-content select="mat-hint:not([align='end'])"></ng-content>
<div class="mat-mdc-form-field-hint-spacer"></div>
<ng-content select="mat-hint[align='end']"></ng-content>
</div>
<div
class="mat-mdc-form-field-error-wrapper mat-mdc-form-field-error-wrapper--hidden"
[@transitionMessages]="_subscriptAnimationState"
>
<ng-content select="mat-error, [matError]"></ng-content>
</div>

<div
class="mat-mdc-form-field-hint-wrapper mat-mdc-form-field-hint-wrapper--hidden"
[@transitionMessages]="_subscriptAnimationState"
>
@if (hintLabel) {
<mat-hint [id]="_hintLabelId">{{hintLabel}}</mat-hint>
}
}
<ng-content select="mat-hint:not([align='end'])"></ng-content>
<div class="mat-mdc-form-field-hint-spacer"></div>
<ng-content select="mat-hint[align='end']"></ng-content>
</div>
</div>
8 changes: 8 additions & 0 deletions src/material/form-field/form-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,11 @@ $_icon-prefix-infix-padding: 4px;
.mdc-notched-outline--upgraded .mdc-floating-label--float-above {
max-width: calc(100% * 4 / 3 + 1px);
}

.mat-mdc-form-field-error-wrapper--hidden {
visibility: hidden;
}

.mat-mdc-form-field-hint-wrapper--hidden {
visibility: hidden;
}
43 changes: 43 additions & 0 deletions src/material/form-field/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ export class MatFormField
this._stateChanges = control.stateChanges.subscribe(() => {
this._updateFocusState();
this._syncDescribedByIds();
this._showOrHideSubscript();
this._changeDetectorRef.markForCheck();
});

Expand Down Expand Up @@ -478,17 +479,20 @@ export class MatFormField
// Re-validate when the number of hints changes.
this._hintChildren.changes.subscribe(() => {
this._processHints();
this._showOrHideSubscript();
this._changeDetectorRef.markForCheck();
});

// Update the aria-described by when the number of errors changes.
this._errorChildren.changes.subscribe(() => {
this._syncDescribedByIds();
this._showOrHideSubscript();
this._changeDetectorRef.markForCheck();
});

// Initial mat-hint validation and subscript describedByIds sync.
this._validateHints();
this._showOrHideSubscript();
this._syncDescribedByIds();
}

Expand Down Expand Up @@ -682,6 +686,45 @@ export class MatFormField
}
}

/**
* Solves https://github.com/angular/components/issues/29616
* Issues with certain browser and screen reader pairings not able to announce mat-error
* when it's added to the DOM rather than changing the visibility of the hint/error wrappers.
* Changing visibility instead of adding the div wrappers works for all browsers and sreen
* readers.
*
* If there is an 'error' or 'hint' message being returned, remove visibility: hidden
* style class and show error or hint section of code. If no 'error' or 'hint' messages are
* being returned and no error children showing in query list, add visibility: hidden
* style class back to error wrapper.
*/
private _showOrHideSubscript() {
switch (this._getDisplayedMessages()) {
case 'error': {
console.log(this._elementRef.nativeElement.children[1].children[0].classList);
this._elementRef.nativeElement.children[1].children[0].classList.remove(
'mat-mdc-form-field-error-wrapper--hidden',
);
console.log(this._elementRef.nativeElement.children[1].children[0].classList);
break;
}
case 'hint': {
console.log(this._elementRef.nativeElement.children[1].children[1].classList);
this._elementRef.nativeElement.children[1].children[1].classList.remove(
'mat-mdc-form-field-hint-wrapper--hidden',
);
console.log(this._elementRef.nativeElement.children[1].children[1].classList);
break;
}
}

if (!this._errorChildren || this._errorChildren.length === 0 || !this._control.errorState) {
this._elementRef.nativeElement.children[1].children[0].classList.add(
'mat-mdc-form-field-error-wrapper--hidden',
);
}
}

/**
* Updates the horizontal offset of the label in the outline appearance. In the outline
* appearance, the notched-outline and label are not relative to the infix container because
Expand Down

0 comments on commit e9228db

Please sign in to comment.