Как разрешить программам чтения с экрана объявлять сообщения проверки формы ASP.NET MVC 5 при перемещении фокуса на ошибочное поле?

У нас есть веб-приложение ASP.NET MVC 5. Мы регулярно тестируем доступность с помощью JAWS в сочетании с Internet Explorer 11 (предприятие) и Chrome. Мы продолжаем сталкиваться с проблемами, когда JAWS не считывает сообщения проверки, связанные с полями формы, когда пользователь вводит в поле TAB. Мы используем 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-модулей?


person Greg Burghardt    schedule 14.08.2018    source источник


Ответы (3)


Без создания пользовательских методов расширения HtmlHelper для создания атрибута aria-describedby в элементе управления for и связанного атрибута id в элементе error вам потребуется использовать 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 и включить его в ваш пакет jquery или jqueryval, чтобы он включался во все представления, включающие формы для создания или редактирования данных.

person Community    schedule 22.09.2018
comment
После того, как вчера я поиграл с вещами, это было в основном направление, в котором я начал двигаться. На самом деле я строил aria-describedby на фокусе/фокусине. Мне все еще нужно протестировать решение JavaScript с помощью JAWS. - person Greg Burghardt; 22.09.2018
comment
У нас есть много полей формы, которые динамически генерируются с помощью JavaScript. Хотя базовый алгоритм работает правильно, событие DOMContentLoaded не перехватывает эти новые поля. И плагин проверки jQuery, кажется, иногда также запускает размытие для определенных полей. И у меня есть настройка JavaScript для новых вновь созданных полей. О, какую запутанную паутину я сплела... - person Greg Burghardt; 24.09.2018
comment
Если вы динамически добавляете новые элементы управления формой, вам просто нужно добавить соответствующие атрибуты class и id, но вы не отметили это в своем вопросе и не показали, как вы их добавляете, поэтому невозможно включить код для этого. - person ; 25.09.2018
comment
Проверка jQuery является «ленивой» и запускается .blur(), а затем '.keyup() (и я предполагаю, что вы повторно анализируете $.validator при добавлении новых элементов в DOM? - см. Проверка обязательных полей не работает во всплывающем окне JQuery MVC 4) - person ; 25.09.2018
comment
Пока мы занимаемся забавными вещами с динамическим добавлением элементов, этот ответ поставил меня на правильный путь. Молодец, сэр! - person Greg Burghardt; 26.09.2018
comment
Решение, которое сработало для нас, заключалось в прослушивании событий размытия и фокуса на этапе захвата, поэтому jQuery не работал, поскольку он прослушивал события только на этапе всплытия. Но после ответа на событие шаги были точно такими же. Вручную совместите атрибут aria-describedby с сообщениями проверки. - person Greg Burghardt; 26.09.2018

С точки зрения чистого 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. Если инфраструктура не позволяет связать описание с полем, то инфраструктура несовершенна, и в инфраструктуру следует отправить запрос функции.

person slugolicious    schedule 14.08.2018

Я использую ненавязчивую проверку с помощью атрибутов data-val-* и создаю промежутки, которые содержат сообщения об ошибках проверки, чтобы я мог контролировать размещение. При этом я также могу легко назначить им идентификатор и использовать aria-describedby. Когда возникает ошибка и диапазон заполняется, когда клиент фокусируется на вводе, считыватель находит соответствующий идентификатор диапазона и считывает появившуюся там ошибку. Ключевым моментом здесь является то, что 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>
person AaronLS    schedule 10.04.2020