0

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!

user2552949
  • 1
  • 1
  • 3

1 Answers1

0

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.

slugolicious
  • 15,824
  • 2
  • 29
  • 43
  • updated the original post please see if you have any solution for this- thanks in advance – user2552949 Apr 25 '18 at 06:16
  • if you have straight html, i might be able to help, but your code example has a bunch of other programming logic so it's difficult to see what's generated. – slugolicious Apr 25 '18 at 19:07
  • added the html before and after the error regions are generated. – user2552949 Apr 27 '18 at 09:11
  • The second code snippet just has `
    `. The two `
    ` sections in both snippets are the same, other than the order of some of the attributes. Shouldn't the second one have an element with "Your first name is required" as shown in your NVDA speech viewer image?
    – slugolicious Apr 27 '18 at 17:58