-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(material/form-field): make mat-errors more polite #21870
Conversation
src/material/form-field/error.ts
Outdated
}, | ||
providers: [{provide: MAT_ERROR, useExisting: MatError}], | ||
}) | ||
export class MatError { | ||
@Input() id: string = `mat-error-${nextUniqueId++}`; | ||
|
||
@Input() live: AriaLivePoliteness = 'polite'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crisbeto what's the normal strategy we use for giving a default value to an aria- attribute but allowing a custom value to be set by the user if they want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually we match the attribute name so in this case it should be @Input('aria-live')
. Also I think that we should type it as string
since the AriaLivePoliteness
is tied to the LiveAnnouncer
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember some stuff about injecting @Attribute
in the constructor in some cases, does that have any advantage over just doing @Input('aria-live')
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with making it an input is that it won't pick up a value set as [attr.aria-live]
. It can be worked around by doing something like:
constructor(@Attribute('aria-live') defaultAriaLive) {
if (!defaultAriaLive) {
element.setAttribute('aria-live', 'polite');
}
}
I like the Input
, because it allows us to document it, but I don't feel strongly about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can base the value on the injected @Attribute
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrisbubernak something like this:
@Input('aria-live') ariaLive: string = this._ariaLive ?? 'polite';
constructor(@Attribute('aria-live') private _ariaLive: string) {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmalerba I updated the code to include this and verified [attr.aria-live] works, PTAL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @mmalerba , it looks like I was slightly mistaken the [attr.aria-live] case does not work in my current CL. The root issue seems to be that the injected @Attribute('aria-live') only has a non-null value when the literal "aria-live" attribute is used. Setting [attr.aria-live] or [aria-live] leave _ariaLive with a null value.
In fact, the only way that I can currently think of to detect that a value was set via [attr.aria-live] is to way until ngAfterViewInit and then inspect the dom directly.
While I don't love the idea of mucking with the native element directly this is the best idea I have right now that seems to work for all cases while correctly falling back on a default if needed. Basically just wait till after view init, see if we have a value set and if not use the Input bound property which will either have a supplied value OR make sure the default gets stamped in.
@Input('aria-live') ariaLive: string = this._ariaLive ?? 'polite';
constructor(@Attribute('aria-live') private _ariaLive, private _elementRef: ElementRef, ){}
ngAfterViewInit() {
// At this point [attr.aria-live] and aria-live will have modified the dom if
// either was present, just handle the case where [aria-live] syntax was used.
if(!this._elementRef.nativeElement.ariaLive){
this._elementRef.nativeElement.setAttribute('aria-live', this.ariaLive);
}
}
WDYT? Am I missing something obvious here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that seems like a reasonable solution to me. It's a pain that this isn't easier to accomplish
I know that this change leads to some test breakages but just wanted to get verification that this approach is appropriate (or guidance on an alternative solution) before proceeding to fix everything up. |
@chrisbubernak yes, overall this seems like a good change to me |
bcd5cf6
to
5ee4539
Compare
70a8070
to
2ba8aa8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left comment about aria-atomic.
8540e05
to
135d829
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
90cca32
to
99f39bd
Compare
0407859
to
0a3ece4
Compare
Make the "politeness" of mat-error "polite" by default (instead of "assertive") and also make this configurable via an input binding. Fixes #21781
9c0e1ae
to
0b23261
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for taking the time to make this PR!
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Make the "politeness" of mat-error "polite" by default (instead of "assertive") and also make this configurable via an input binding.
Fixes #21781