6

我们有一个 ASP.NET MVC 5 Web 应用程序。我们结合 Internet Explorer 11(企业授权)和 Chrome 使用 JAWS 进行定期可访问性测试。当用户 TAB 进入字段时,我们一直遇到 JAWS 无法读取与表单字段关联的验证消息的问题。我们使用 FluentValidation 和标准 HTML 助手来显示表单字段和验证消息(示例如下):

@Html.LabelFor(model => model.Email)
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email, null, new { role = "alert" })

示例 FluentValidation 可能会在数据库中查询表单中的电子邮件地址,并显示在服务器端运行的“此电子邮件已被占用”的消息。

发送回浏览器的结果 HTML 是:

<label for="Email">E-mail address:</label>

<input type="text" name="Email" id="Email" ...>

<span class="..." data-valmsg-for="Email" data-valmsg-replace="true" role="alert">
    This e-mail has already been taken
</span>

没有将验证消息与表单字段相关联。我一直认为 MVC 框架会自动建立这种连接,但显然它没有。

根据WebAIM的说法,我们应该利用该aria-describedby属性将表单字段与内联验证错误相关联,但要重新检测现有的 MVC5 框架来做到这一点是一项艰巨的任务。

当将焦点放在由 ASP.NET MVC5 生成的表单字段时,我们如何在不重写主要 HTML 帮助程序的情况下让屏幕阅读器宣布内联验证消息?

4

3 回答 3

8

如果不创建自定义HtmlHelper扩展方法来生成aria-describedbyfor 控件中的属性以及 error 元素中的关联id属性,您将需要使用 javascript 来添加它们。

请注意,每个错误消息占位符(由 生成)通过属性@Html.ValidationMessageFor()与其表单控件相关联。data-valmsg-for="...."

假设您想要包含aria-describedby带有关联错误消息的所有表单控件(并且在<form>元素内),以便在通过添加客户端错误时它可用jquery.validate.js,那么脚本 ( jQuery) 将是

$(function () {
    // Get the form controls
    var controls = $('form').find('input, textarea, select')
        .not(':hidden, :input[type=submit], :input[type=button], :input[type=reset]');
    $.each(controls, function (index, item) {
        // Get the name of the form control
        var name = $(this).attr('name'); 
        if (!name) {
            return true;
        }
        // Get the associated error element
        var errorElement = $('[data-valmsg-for="' + name + '"]');
        if (!errorElement) {
            return true;
        }
        // Generate an id attribute based on the name of the control
        var errorId = name + "-error"
        // Add attributes to the input and the error element
        $(this).attr('aria-describedby', errorId)
        errorElement.attr('id', errorId);
    });
});

如果您对客户端验证错误不感兴趣,那么您可以将var controls = $('.input-validation-error');其用作选择器来仅获取添加了服务器端验证错误的表单控件。

我建议将此脚本包含在外部(比如说)screenreadervalidation.js文件中,并将其包含在您的jqueryjqueryval捆绑包中,以便将其包含在所有包含用于创建或编辑数据的表单的视图中。

于 2018-09-22T08:30:56.463 回答
2

从纯 html 的角度来看,aria-describedby属性是您处理它的方式。

<label for="Email">E-mail address:</label>
<input type="text" id="Email" aria-describedby="more_stuff">
<span id="more_stuff">
    This e-mail has already been taken
</span>

我不确定为什么需要“重新安装”框架或编写“主要”帮助程序,但我不是 asp.net 用户。如果框架不允许您将描述与字段相关联,则框架存在缺陷,应向框架提交功能请求。

于 2018-08-14T20:12:22.403 回答
0

我通过data-val-*属性使用不显眼的验证并创建保存验证错误消息的跨度,以便我可以控制放置。在这样做时,我还可以轻松地为他们分配一个 ID 并使用aria-describedby. 当发生错误并在客户专注于输入时填充跨度时,读取器会找到相关的跨度 ID 并读取出现在那里的错误。这里的关键部分是aria-describedby="NameOfCustomerError"匹配id="NameOfCustomerError"错误将出现的位置(因为它是data-valmsg-for="NameOfCustomer"指示它自动显示该输入错误的元素)。

<input data-val="true"
   data-val-required="@($"{CustomerResource.Label_Name}: {SharedResource.Validation_General}")"
   data-val-minlength-min="4"
   data-val-minlength="@CustomerResource.Validation_NameOfCustomer"
   type="text" maxlength="100"
   name="NameOfCustomer" id="NameOfCustomer"
   class="form-control" aria-describedby="NameOfCustomerError"
   placeholder="@CustomerResource.Label_Name" />

<span role="alert" id="NameOfCustomerError" class="field-validation-valid text-danger" data-valmsg-for="NameOfCustomer" data-valmsg-replace="true"></span>
于 2020-04-10T19:54:10.770 回答