Skip to content

Commit

Permalink
feat(material/form-field): make mat-errors more polite
Browse files Browse the repository at this point in the history
Make the "politeness" of mat-error "polite" by default (instead of "assertive") and also make this
configurable via an input binding.

Fixes #21781
  • Loading branch information
chrisbubernak committed Feb 17, 2021
1 parent aa7dc00 commit 135d829
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/material-experimental/mdc-chips/chip-grid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -905,11 +905,11 @@ describe('MDC-based MatChipGrid', () => {
});
}));

it('should set the proper role on the error messages', () => {
it('should set the proper aria-live attribute on the error messages', () => {
errorTestComponent.formControl.markAsTouched();
fixture.detectChanges();

expect(containerEl.querySelector('mat-error')!.getAttribute('role')).toBe('alert');
expect(containerEl.querySelector('mat-error')!.getAttribute('aria-live')).toBe('polite');
});

it('sets the aria-describedby to reference errors when in error state', () => {
Expand Down
9 changes: 7 additions & 2 deletions src/material-experimental/mdc-form-field/directives/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, InjectionToken, Input} from '@angular/core';
import {Attribute, Directive, InjectionToken, Input} from '@angular/core';

let nextUniqueId = 0;

Expand All @@ -22,11 +22,16 @@ export const MAT_ERROR = new InjectionToken<MatError>('MatError');
selector: 'mat-error',
host: {
'class': 'mat-mdc-form-field-error mat-mdc-form-field-bottom-align',
'role': 'alert',
'aria-atomic': 'true',
'[attr.aria-live]': 'ariaLive',
'[id]': 'id',
},
providers: [{provide: MAT_ERROR, useExisting: MatError}],
})
export class MatError {
@Input() id: string = `mat-mdc-error-${nextUniqueId++}`;

@Input('aria-live') ariaLive: string = this._ariaLive ?? 'polite';

constructor(@Attribute('aria-live') private _ariaLive: string) {}
}
4 changes: 2 additions & 2 deletions src/material-experimental/mdc-input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1037,11 +1037,11 @@ describe('MatMdcInput with forms', () => {
.toBe(1, 'Expected one hint to still be shown.');
}));

it('should set the proper role on the error messages', fakeAsync(() => {
it('should set the proper aria-live attribute on the error messages', fakeAsync(() => {
testComponent.formControl.markAsTouched();
fixture.detectChanges();

expect(containerEl.querySelector('mat-error')!.getAttribute('role')).toBe('alert');
expect(containerEl.querySelector('mat-error')!.getAttribute('aria-live')).toBe('polite');
}));

it('sets the aria-describedby to reference errors when in error state', fakeAsync(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/material/chips/chip-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1282,11 +1282,11 @@ describe('MatChipList', () => {
});
}));

it('should set the proper role on the error messages', () => {
it('should set the proper aria-live attribute on the error messages', () => {
errorTestComponent.formControl.markAsTouched();
fixture.detectChanges();

expect(containerEl.querySelector('mat-error')!.getAttribute('role')).toBe('alert');
expect(containerEl.querySelector('mat-error')!.getAttribute('aria-live')).toBe('polite');
});

it('sets the aria-describedby to reference errors when in error state', () => {
Expand Down
9 changes: 7 additions & 2 deletions src/material/form-field/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, InjectionToken, Input} from '@angular/core';
import {Attribute, Directive, InjectionToken, Input} from '@angular/core';

let nextUniqueId = 0;

Expand All @@ -22,11 +22,16 @@ export const MAT_ERROR = new InjectionToken<MatError>('MatError');
selector: 'mat-error',
host: {
'class': 'mat-error',
'role': 'alert',
'[attr.id]': 'id',
'aria-atomic': 'true',
'[attr.aria-live]': 'ariaLive',
},
providers: [{provide: MAT_ERROR, useExisting: MatError}],
})
export class MatError {
@Input() id: string = `mat-error-${nextUniqueId++}`;

@Input('aria-live') ariaLive: string = this._ariaLive ?? 'polite';

constructor(@Attribute('aria-live') private _ariaLive: string) {}
}
4 changes: 2 additions & 2 deletions src/material/input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1193,11 +1193,11 @@ describe('MatInput with forms', () => {
.toBe(1, 'Expected one hint to still be shown.');
}));

it('should set the proper role on the error messages', fakeAsync(() => {
it('should set the proper aria-live attribute on the error messages', fakeAsync(() => {
testComponent.formControl.markAsTouched();
fixture.detectChanges();

expect(containerEl.querySelector('mat-error')!.getAttribute('role')).toBe('alert');
expect(containerEl.querySelector('mat-error')!.getAttribute('aria-live')).toBe('polite');
}));

it('sets the aria-describedby to reference errors when in error state', fakeAsync(() => {
Expand Down
6 changes: 4 additions & 2 deletions tools/public_api_guard/material/form-field.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ export declare const MAT_PREFIX: InjectionToken<MatPrefix>;
export declare const MAT_SUFFIX: InjectionToken<MatSuffix>;

export declare class MatError {
ariaLive: string;
id: string;
static ɵdir: i0.ɵɵDirectiveDefWithMeta<MatError, "mat-error", never, { "id": "id"; }, {}, never>;
static ɵfac: i0.ɵɵFactoryDef<MatError, never>;
constructor(_ariaLive: string);
static ɵdir: i0.ɵɵDirectiveDefWithMeta<MatError, "mat-error", never, { "id": "id"; "ariaLive": "aria-live"; }, {}, never>;
static ɵfac: i0.ɵɵFactoryDef<MatError, [{ attribute: "aria-live"; }]>;
}

export declare class MatFormField extends _MatFormFieldMixinBase implements AfterContentInit, AfterContentChecked, AfterViewInit, OnDestroy, CanColor {
Expand Down

0 comments on commit 135d829

Please sign in to comment.