Доступные сообщения валидации формы с помощью ARIA и Vue.js

В данной статье вы узнаете, как использовать ARIA и Vue.js, чтобы сделать сообщения об ошибках валидации формы и инструкции доступными для посетителей с ограниченными функциями.

Как программы чтения с экрана перемещаются по формам и читают их

Разработчик должен понимать различия между тем, как зрячий посетитель взаимодействует с формой, и как воспринимает ее посетитель программы чтения с экрана. Они используют «скрытое» измерение веб-страницы, известное как «дерево доступности». Accessibility tree — это структура, которая может программам чтения с экрана приобретать информацию из браузера.

Для навигации по веб-форме программное обеспечение для чтения с экрана используют режим, известный как «форма» или «фокус». Этот режим может посетителю перемещаться по интерактивным элементам управления формой при помощи клавиатуры. Когда в фокус попадает элемент управления, программа чтения с экрана считывает поле ввода ввода и связанную с ним метку.

Доступ к сообщениям об ошибках и инструкциям

А как насчет доступа к сообщениям об ошибках валидации или инструкций для полей ввода? Если поместить их в элемент, который не может быть выделен фокусом ввода(к примеру, <div> или <p>), то программа чтения с экрана пропустит их. Как это исправить?

Метод 1: Что содержится в имени?

Самый простой метод обеспечить доступность сообщений об ошибках валидации — сделать их дочерними элементами относительно <label>. Сделав сообщение об ошибке являются частью label, оно становится доступным через элемент ввода. Оно будет прочитано, когда элемент управления попадет в фокус ввода.

Для этого используется директива Vue v-show. Она скрывает сообщение, пока не возникнет ошибка валидации. В том числе и от программ чтения с экрана.

Метод 2: Использовать aria-describedby

Но что, если необходимо, чтобы в элементе <label> не было сообщений об ошибках? В таком случае лучше использовать атрибуты ARIA. Они влияют на то, как экранные дикторы интерпретируют страницы по дереву доступности.

ARIA предлагает атрибут, который может разработчикам связать иные HTML-элементы с полями ввода формы — aria-describedby. Для предоставления инструкций для поля ввода формы добавьте к нему атрибут aria-describedby с id каждого элемента, который вы хотели бы связать с input.

<label for="first_name">First Name:</label><input id="first_name" type="text" aria-describedby="first_name-instructions"><div id="first_name-instructions">maximum length 30 characters</div>

Сейчас, когда мы явно связали дополнительные инструкции с полем ввода, добавим сообщения об ошибках:

<div id="first_name-error">Please enter a valid project name.</div><label for="first_name">First Name:</label><div id="first_name-instructions">maximum length 30 characters</div><input id="first_name" name="first_name" type="text" aria-describedby="first_name-instructions first_name-error">

При помощи одного простого атрибута мы добавили сообщение об ошибке и связали его с полем ввода формы.

Vue.js упрощает реализацию

Сейчас необходимо добиться, чтобы сообщение об ошибке не отображалось и читалось постоянно, а только когда возникла ошибка. Для этого мы используем библиотеку Vuelidate.

<div id="first_name-error" v-show="first_name.$error">Please enter a valid project name.</div><label for="first_name">First Name:</label><div id="first_name-instructions">maximum length 30 characters</div><input id="first_name" name="first_name" type="text" v-model="$v.first_name.$model":aria-invalid="$v.first_name.$invalid" aria-describedby="first_name-instructions first_name-error">

Сейчас у нас есть сообщение об ошибке, которое связано с полем ввода ввода. И оно будет скрыто, если ошибка валидации не произошла.

Но поскольку мы используем v-show, то сообщение будет скрыто и от программ чтения с экрана. Здесь мы сталкиваемся с особенностью атрибута aria-describedby. По умолчанию связанный элемент будет считываться, даже если он будет скрыть.

Так что нам необходимо сделать aria-describedby динамическим, чтобы он добавлял идентификатор сообщения об ошибке только тогда, когда она возникла. Это просто реализовать благодаря Vue.js:

signup-form.html

<div id="first_name-error" v-show="first_name.$error">Please enter a valid first name</div><label for="first_name">First Name:</label><div id="first_name-instructions">maximum length 30 characters</div><input id="first_name" name="first_name" type="text" v-model="$v.first_name.$model":aria-invalid="$v.first_name.$invalid":aria-describedby="describedBy('first_name')">

main.js

methods: { // генерация связанных с aria-describedby идентификаторов describedBy(field) { const inst = `${field}-instructions` // field.$error - это логическое вычисляемое свойство, возвращаемое Vuelidate // если возникла ошибка, valErr становится равным идентификатору поля ввода. В противном случае это пустая строка.      const valErr = field.$error? `${field}-error`: ''            //обрезаем и заменяем двойные пробелы одиночными let refString =  ` $ {valErr} ${inst}`.replace(/s+/g,' ').trim()        return refString    }     // базовый конструктор сообщений об ошибках vMessage(v, field) {        let message = ''        let errors = []        if($v.$error)) {            // получаем тип ошибки из $params Vuelidate let errorTypeKeys = Object.keys($v["$params"])            // составляем массив ошибок for(const key of errorTypeKeys) {                if($v[key] === false) {                    errors.push(key)                }            }                    //создаем из массива разделенную запятыми строку let errorString = errors.length > 1          ? errors.join(', ')            : errors[0]                    // преобразуем в читаемое сообщение errorString = errorString                .replace('required', 'This is a required field')                .replace('url', 'The url is invalid')                .replace('email', 'The email address is invalid')                .replace('minLength', 'Input does not meet minimum length')            message = `${errorString}.`        }        return messsage    }}

Сейчас у нас есть динамический атрибут aria-describedby , который связан с выводом способа describedBy() . Он принимает имя поля ввода в виде параметры. Далее определяет, будет ли ввод поля ввода действительным, и возвращает список идентификаторов.

Если возникла ошибка и <input> выделен фокусом ввода, то атрибут aria-describedby будет ссылаться на сообщение об ошибке и на инструкции. В противном случае программа чтения с экрана объявит только инструкции (содержимое <label> будет зачитано в любом случае).

Некоторые предостережения

Разработчики должны знать, что программы чтения с экрана также отличаются друг от друга. Они могут интерпретировать html или ARIA по-своему, иметь собственные наборы возможностей. При этом их функционал может различаться при использовании в сочетании с разными браузерами.

К примеру, и JAWS, и NVDA поддерживают режим формы (фокуса) и aria-describedby. А Voiceover поддерживает атрибут aria-describedby, но у него нет режима фокуса или формы. NVDA наиболее надежно работает с Firefox, а Voiceover — с Safari.

Необходимо учитывать, что в дополнение к чтению скрытых связанных элементов, aria-describedby игнорирует семантику. Он считывает список связанных элементов как непрерывную строку.

Если инструкции и сообщения содержат списки или иные вложенные элементы, семантика будет игнорироваться. Так что лучше всего сделать содержимое сообщений об ошибках коротким и простым, а также использовать пунктуацию.

Будущее: aria-errormessage

В конце 2017 года в ARIA 1.1 был добавлен атрибут aria-errormessage , предназначенный для сообщений об ошибках валидации. Когда атрибут получит поддержку программами чтения с экрана и браузерами, он будет использоваться вместе с aria-invalid , чтобы обеспечить более согласованный способ считывания сообщений об ошибке.

Тестирование

Единственный метод убедиться в правильной работе формы – это протестировать ее через программу для чтения с экрана.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *