简体   繁体   中英

NVDA screen reader aria-live issue

Using aria-live to show form field validation error dynamically. Everything works, except when moving from one field to another using down arrow key/tab the validation error is only get announced once the next file label is selected, and reads that next label name then announces the previous fields validation error.

Code:

{!label ? null : <label htmlFor={`input-${model}`} className={classnames('inputLabel', `${model.toLowerCase()}-label`)}>{label}&nbsp;<i className={ classnames('fa','fa-asterisk', { 'isRequired' : requiredField }, { 'invisible' : !requiredField || !showAsterisk } )} aria-hidden='true'></i></label>}              
            {!label ? null : <br />}
            <OverlayTrigger ref={(input) => { this.refPopOver = input; }} trigger={trigger} placement={popoverPlacement} overlay={popover} shouldUpdatePosition={true}>
                <InputComponent model={`.${model}`}

                    {...extraProps} />
            </OverlayTrigger>
            <div id='errorRegion' aria-atomic="true" aria-live="assertive">
                <Errors
                    className={classnames('errorText', 'error', model.toLowerCase())}
                    model={`.${model}`}
                    wrapper={ErrorWrapper}
                    show="touched"
                    messages={validators.messages}
                />
            </div>

EDIT: slugolicious- thanks for you update. yes, I am using aria-live for announcing error. It works fine when using tab to go through the focusable elements. But when using browse mode using down arrow the sequence of announcing error and next label gets mixed up, I have also tried you suggestion but still the same result; its announce next label then error message of previous field. adding log of NVDA(v2017.4 & v2018.1) using Firefox (59.0.2 x64) below-

NVDA speech viewer log Second Edit: before the live regions are populated

<form style="position: relative;" autocomplete="off">
    <div class="row">
        <div class="col-sm-12">
            <div class="id-form-errors" aria-live="assertive" aria-atomic="true">
                <!-- react-empty: 170 -->
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-xs-12 col-sm-12" style="margin-bottom: 20px;">
            <div style="position: relative;">
                <label class="inputLabel firstname-label" for="input-firstName">
                    <!-- react-text: 175 -->First name
                    <!-- /react-text -->
                    <!-- react-text: 176 -->&nbsp;
                    <!-- /react-text -->
                    <i class="fa fa-asterisk isRequired" aria-hidden="true"></i>
                </label>
                <br>
                <input name="appForms.identify.firstName" class="field fullWidth firstname-field" id="input-firstName" aria-required="true"
                    aria-describedby="firstname-popover" type="text" placeholder="First name" value="">
                <div id="errorRegion" aria-live="assertive" aria-atomic="true">
                    <!-- react-empty: 181 -->
                </div>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12" style="margin-bottom: 20px;">
            <div style="position: relative;">
                <label class="inputLabel lastname-label" for="input-lastName">
                    <!-- react-text: 185 -->Last name
                    <!-- /react-text -->
                    <!-- react-text: 186 -->&nbsp;
                    <!-- /react-text -->
                    <i class="fa fa-asterisk isRequired" aria-hidden="true"></i>
                </label>
                <br>
                <input name="appForms.identify.lastName" class="field fullWidth lastname-field" id="input-lastName" aria-required="true"
                    aria-describedby="lastname-popover" type="text" placeholder="Last name" value="">
                <div id="errorRegion" aria-live="assertive" aria-atomic="true">
                    <!-- react-empty: 191 -->
                </div>
            </div>
        </div>
    <div class="row">
        <div class="col-xs-12 col-sm-12">
            <button class="submitButton fullWidth disabledButton next-btn" aria-disabled="true" type="submit">Next</button>
        </div>
    </div>
</form>

HTML After error regions are generated:

<div class="row">
    <div class="col-xs-12 col-sm-12" style="margin-bottom: 20px;">
        <div style="position: relative;">
            <label for="input-firstName" class="inputLabel firstname-label">
                <!-- react-text: 226 -->First name
                <!-- /react-text -->
                <!-- react-text: 227 -->&nbsp;
                <!-- /react-text -->
                <i class="fa fa-asterisk isRequired" aria-hidden="true"></i>
            </label>
            <br>
            <input type="text" class="field fullWidth firstname-field" placeholder="First name" id="input-firstName" aria-describedby="firstname-popover"
                aria-required="true" name="appForms.identify.firstName" value="">
            <div id="errorRegion" aria-atomic="true" aria-live="assertive">
                <!-- react-empty: 232 -->
            </div>
        </div>
    </div>
    <div class="col-xs-12 col-sm-12" style="margin-bottom: 20px;">
        <div style="position: relative;">
            <label for="input-lastName" class="inputLabel lastname-label">
                <!-- react-text: 236 -->Last name
                <!-- /react-text -->
                <!-- react-text: 237 -->&nbsp;
                <!-- /react-text -->
                <i class="fa fa-asterisk isRequired" aria-hidden="true"></i>
            </label>
            <br>
            <input type="text" class="field fullWidth lastname-field" placeholder="Last name" id="input-lastName" aria-describedby="lastname-popover"
                aria-required="true" name="appForms.identify.lastName" value="">
            <div id="errorRegion" aria-atomic="true" aria-live="assertive">
                <!-- react-empty: 242 -->
            </div>
        </div>
    </div>
</div>

3rd EDIT- Still waiting for a workable solution. Need help!

Just to make sure we're talking about the same thing, using aria-live is for when content on your page updates and you want the update announced immediately by the screen reader. The update is announced once and then it's done. Having error messages announced via aria-live is a good practice.

If the user then navigates through the page, either tabbing around to interactive elements, or using the virtual cursor in a screen reader, your error messages will not be announced unless you've associated them with the field that contains the error, often via the aria-describedby attribute. You should also use aria-invalid="true" on fields that are invalid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM