Содержание
- Валидация форм на стороне клиента
- Что такое валидация формы?
- Типы валидации на стороне клиента
- Использование встроенной валидации форм
- Примеры встроенной валидации форм
- Простой начальный файл
- Атрибут required
- Валидация с помощью регулярного выражения
- Ограничение длины вводимых значений
- Ограничение допустимых значений
- Полный пример
- Валидация форм с помощью JavaScript
- Constraint Validation API
- Реализация кастомного сообщения об ошибке
- Более подробный пример
- Проверка форм без встроенного API
- Пример без использования Constraint Validation API
- Проверьте свои навыки!
- Заключение
Валидация форм на стороне клиента
Перед отправкой данных на сервер важно убедиться, что все обязательные поля формы заполнены данными в корректном формате. Это называется валидацией на стороне клиента и помогает убедиться, что данные, введённые в каждый элемент формы, соответствуют требованиям. Данная статья проведёт вас через основные концепци и примеры валидации на стороне клиента.
Начальные требования: | Владение компьютером, достаточное понимание HTML, CSS, и JavaScript. |
---|---|
Цель: | Понять, что такое валидация на стороне клиента, почему это важно и как применять различные техники для её реализации. |
Валидация на стороне клиента — это первичная проверка введённых данных, которая существенно улучшает удобство взаимодействия с интерфейсом; обнаружение некорректных данных на стороне клиента позволяет пользователю немедленно их исправить. Если же проверка происходит только на сервере, процесс заполнения может быть более трудоёмким, так как требует повторения одних и тех же действий отправки данных на сервер для получения обратного ответа с сообщением о том, что нужно исправить.
Однако, не следует рассматривать валидацию на стороне клиента как достаточную меру безопасности! Любые данные, отправляемые через форму, необходимо дополнительно проверять на безопасность и на стороне сервера, поскольку валидацию на стороне клиента достаточно просто обойти и она может не остановить злоумышленников. Чтобы лучше понимать потенциальные угрозы, рекомендуем ознакомиться с разделом Безопасность вебсайтов; валидация на стороне сервера выходит за рамки этого модуля, но о ней следует помнить.
Что такое валидация формы?
Зайдите на любой популярный сайт, имеющий форму регистрации. Вы заметите, что при вводе данных в неправильном формате, пользователя сразу уведомляют о наличии проблемы. Вы получите примерно такое сообщение:
- «Обязательное поле» (Вы не можете оставить поле пустым).
- «Пожалуйста, введите номер телефона в формате xxx-xxxx» (Чтобы данные считались корректными, их необходимо указать в определённом формате).
- «Пожалуйста, введите корректный email-адрес» (вы ввели данные в неправильном формате).
- «Длина пароля должна быть от 8 до 30 символов и включать одну заглавную букву, один символ, и одну цифру.» (Требования к формату данных достаточно конкретные).
Это называется валидацией формы. По мере ввода, браузер и/или сервер проверяют данные, чтобы определить, соответствуют ли они требуемому формату. Валидация, выполняемая в браузере, называется валидацией на стороне клиента, а выполняемая на сервере — валидацией на стороне сервера. В этом разделе мы сосредоточимся на валидации, выполняемой на стороне клиента.
Если формат корректен, приложение позволяет отправить данные на сервер и (обычно) сохранить в базу данных; в противном случае выводится сообщение с описанием того, что нужно исправить, позволяя ввести данные снова.
Мы хотим максимально упростить заполнение веб-форм. Тогда почему мы настаиваем валидации данных? На это есть три основные причины:
- Мы хотим получать правильные данные в правильном формате. Наши приложения не будут работать должным образом, если данные от пользователей хранятся в неправильном формате, некорректны сами по себе или вовсе пропущены.
- Мы хотим защитить данные пользователей. Принуждение пользователей вводить надёжные пароли облегчает защиту их аккаунтов.
- Мы хотим защитить себя. Существует множество способов, позволяющих злоумышленникам с помощью незащищённых форм навредить приложению (смотрите Безопасность вебсайтов).
Предупреждение: Никогда не доверяйте данным, передаваемым на сервер клиентской программой. Даже если ваша форма правильно валидируется и не допустит введение потенциально вредоносных данных на стороне клиента, злоумышленники по-прежнему могут изменить сетевой запрос.
Типы валидации на стороне клиента
Существует два типа валидации на стороне клиента, с которыми вы столкнётесь в Интернете:
- Встроенная валидация форм использует функционал валидации HTML5, который мы неоднократно обсуждали в этом модуле. HTML5-валидация обычно не требует большого количества JavaScript-кода и демонстрирует лучшую производительность, но не настолько настраиваема, как валидация с помощью JavaScript.
- JavaScript-валидация кодируется с помощью JavaScript. Она полностью настраиваема, но требует программирования всей логики (или использования библиотеки).
Использование встроенной валидации форм
Одной из самых важных функций элементов форм HTML5 (en-US) является способность валидировать бóльшую часть пользовательских данных без использования JavaScript. Это выполняется с помощью атрибутов валидации у элементов формы. Многие из них мы уже рассмотрели в этом курсе:
- required : Определяет, что для отправки формы данное поле предварительно должно быть заполнено.
- minlength и maxlength : Задаёт минимальную и максимальную длину текстовых данных (строк)
- min и max : Задаёт минимальное и максимальное значение для поля, расчитанного на числовой тип данных
- type : Определяет тип данных, на который рассчитано поле: число, email-адрес или какой-то другой предустановленный тип
- pattern : С помощью регулярного выражения, определяет шаблон, которому должны соответствовать вводимые данные.
Если данные, введённые в поле формы, соответствуют правилам перечисленных выше атрибутов, они считаются валидными, если нет — не валидными
Когда элемент валиден, справедливы следующие утверждения:
- Элемент соответствует CSS-псевдоклассу :valid , позволяющему стилизовать только валидные элементы.
- Если пользователь пытается отправить данные, браузер отправит форму при условии, что ничто другое (например, JavaScript) не помешает ему это сделать
Когда элемент не валиден, справедливы следующие утверждения:
- Элемент соответствует CSS-псевдоклассу :invalid или, в зависимости от ошибки, другим псевдоклассам (например, :out-of-range ), которые позволяют применять определённые стили к элементам, не являющимся валидными.
- Если пользователь пытается отправить данные, браузер заблокирует форму и выведет сообщение об ошибке.
Примеры встроенной валидации форм
В этом разделе мы протестируем некоторые из атрибутов, которые обсуждали выше.
Простой начальный файл
Давайте начнём с простого примера: поле, позволяющее указать своё предпочтение — банан или вишня. Этот пример включает обычное текстовое поле , связанный с ним элемент и кнопку отправки формы . Исходный код можно найти на GitHub по адресу fruit-start.html, а ниже приведён рабочий пример.
Для начала скопируйте файл fruit-start.html в новую папку на вашем жёстком диске.
Атрибут required
Самым простым в HTML5-валидации является атрибут required . Добавьте его к элементу, чтобы сделать заполнение обязательным. Элемент с данным атрибутом соответствует CSS-псевдоклассу :required , а если поле ввода пустое, вместо отправки формы отобразится сообщение об ошибке. Пока поле пустое, оно также будет соответствовать CSS-псевдоклассу :invalid .
Добавьте к полю атрибут required , как показано ниже.
Обратите внимание на CSS, который включён в файл примера:
Данный CSS задаёт полю красную пунктирную рамку, когда оно не валидно, а когда валидно — сплошную чёрную. Мы также добавили фоновый градиент для обязательных не валидных полей. Проверьте новое поведение в примере ниже:
Примечание: Рабочий пример можно найти на GitHub по адресу fruit-validation.html (отдельно можно найти исходный код.)
Попробуйте отправить форму без введения значения. Обратите внимание, что не валидное поле получает фокус, появляется сообщение об ошибке («Заполните это поле») и блокируется отправка формы.
Наличие атрибута required у любого элемента, который его поддерживает, означает, что элемент соответствует CSS-псевдоклассу :required , независимо от того, имеет он значение или нет. Если элемент не содержит значение, он будет соответствовать псевдоклассу :invalid .
Примечание: Для повышения удобства взаимодействия указывайте пользователям, какие поля являются обязательными. К тому же, этого требует руководство по обеспечению доступности WCAG. Требуйте обязательного ввода только тех данных, которые вам действительно нужны: например, так ли важно знать пол или должность пользователя?
Валидация с помощью регулярного выражения
Ещё одной полезной функцией валидации является атрибут pattern , который в виде значения принимает Регулярное выражение. Регулярное выражение (regex) — это шаблон, который может быть использован для сопоставления набора символов в текстовой строке, поэтому они идеально подходят для валидации формы и используются для множества других целей в JavaScript.
Регулярные выражения достаточно сложны, и мы не будем подробно рассматривать эту тему в данной статье. Ниже приведены несколько примеров, чтобы дать вам представление о том, как они работают.
- a — Соответствует одному символу a (не b , не aa , и так далее).
- abc — Соответствует символу a , за которой следует b , за которой следует c .
- ab?c — Соответствует символу a , за которым опционально может следовать b , за которым следует c . ( ac или abc )
- ab*c — Соответствует символу a , за которым опционально может следовать любое количество символов b , за которыми следует c . ( ac , abc , abbbbbc , и так далее).
- a|b — Соответствует символу a или b .
- abc|xyz — Соответствует в точности abc или в точности xyz (но не abcxyz или a или y , и так далее).
Есть еще много возможностей, которые мы не упомянули. Полный список со множеством примеров можно найти в документации по Регулярным выражениям
Давайте рассмотрим пример. Добавьте в атрибут pattern следующий шаблон:
Это даёт нам следующее обновление — опробуйте его:
Примечание: Рабочий пример можно найти на GitHub по адресу fruit-pattern.html (исходный код.)
В этом примере элемент принимает одно из четырёх возможных значений: строку «banana», «Banana», «cherry», или «Cherry». Регулярные выражения чувствительны к регистру, но с помощью шаблона «Aa», вложенного в квадратные скобки, мы сделали поддержку написания слова как с большой, так и с маленькой буквы.
Подставьте в атрибут pattern приведённые выше примеры регулярных выражений, и посмотрите, как это повлияет на валидацию введённого в поле значения. Попробуйте написать свои шаблоны проверки и посмотрите, что получится. По возможности, делайте их связанными с фруктами, чтобы примеры имели смысл.
Если не пустое значение элемента не соответствует шаблону регулярного выражения, input будет соответствовать псевдоклассу :invalid .
Примечание: Некоторым типам элементов для валидации с помощью регулярного выражения не требуется атрибут pattern . Например, поле с типом email валидирует значение по шаблону одного email-адреса или, если присутствует атрибут multiple (en-US) , шаблону списка email-адресов, разделённых запятыми.
Примечание: Элемент
Ограничение длины вводимых значений
Можно ограничить максимально допустимое количество символов для текстовых полей или
(en-US) используя атрибуты minlength (en-US) и maxlength . Поле будет не валидным, если количество символов его содержимого будет меньше minlength (en-US) или больше maxlength .
Зачастую браузеры не позволяют пользователям вводить в текстовое поле значение, длина которого превышает максимально допустимую. Можно существенно повысить удобство использования, если помимо ограничения в атрибуте maxlength добавить доступный индикатор, отображающий текущее и максимально допустимое количество символов, что даст пользователю возможность уместить содержимое в заданные рамки. Хорошим примером является окно написания твита в Twitter. Для реализации такого функционала можно использовать JavaScript, включая решения, использующие maxlength .
Ограничение допустимых значений
В полях, предназначенных для ввода чисел (например, ), диапазон допустимых значений можно определить с помощью атрибутов min и max . Если поле содержит значение за пределами данного диапазона, оно будет не валидным.
Давайте рассмотрим другой пример. Создайте новую копию файла fruit-start.html.
Содержимое элемента замените на:
- Здесь мы в поле с типом text атрибутам minlength и maxlength , задали одинаковое значение 6, что соответствует количеству символов в словах banana и cherry.
- В поле с типом number атрибуту min мы задали значение 1, а атрибуту max значение 10. При вводе чисел за пределами данного диапазона, поле будет становиться не валидным; с помощью стрелок увеличения/уменьшения пользователи не смогут выйти за границы диапазона. Текущее поле не является обязательным для заполнения, поэтому даже после очистки будет оставаться валидным.
Примечание: Рабочий пример можно найти на GitHub по адресу fruit-length.html (исходный код.)
Примечание: (и другие типы, такие как range и date ) могут также принимать атрибут step (en-US) , который задаёт шаг увеличения или уменьшения значения при использовании кнопок вверх и вниз. В примере выше мы явно не указывали атрибут step , поэтому он получает значение по умолчанию, равное 1 . Это значит, что дробные числа, такие как 3.2, будут не валидными.
Полный пример
Ниже представлен полный пример, демонстрирующий использование встроенного функционала валидации. Сначала немного HTML:
И немного CSS для стилизации HTML:
В статье Атрибуты валидации (en-US) можно найти полный список атрибутов, которые можно использовать для ограничения допустимых значений ввода и типов полей input , которые их поддерживают.
Примечание: Рабочий пример можно найти на GitHub по адресу full-example.html (исходный код.)
Валидация форм с помощью JavaScript
Если нужно управлять внешним видом встроенных сообщений об ошибке или работать с устаревшими браузерами, которые не поддерживают встроенную валидацию форм HTML, вам следует использовать JavaScript. В данном разделе мы рассмотрим различные способы делать это.
Constraint Validation API
Большинство браузеров поддерживают Constraint Validation API, который состоит из набора свойств и методов, доступных на DOM-интерфейсах следующих элементов форм:
Для перечисленных выше элементов Constraint Validation API делает доступными следующие свойства.
- validationMessage : Возвращает локализованное сообщение, описывающее ограничения валидации (если таковые имеются), которым не удовлетворяет определённый элемент. Если элемент не участвует в валидации ( willValidate установлено в false ) или значение элемента удовлетворяет установленным ограничениям (является валидным), будет возвращена пустая строка.
- validity : Возвращает объект ValidityState , который содержит несколько свойств, описывающих состояние валидности элемента. Подробное описание всех свойств доступности можно найти на странице справочника ValidityState ; ниже приведён список наиболее используемых:
- patternMismatch : Возвращает true , если значение не соответствует шаблону, указанному в атрибуте pattern , и false если соответствует. Если true, элемент соответствует CSS-псевдоклассу :invalid .
- tooLong : Возвращает true , если значение длиннее максимальной длины, указанной в атрибуте maxlength , и false если оно короче или равно ей. Если true, элемент соответствует CSS-псевдоклассу :invalid .
- tooShort : Возвращает true , если значение короче минимальной длины, указанной в атрибуте minlength , и false если оно длинее или равно ей. Если true, элемент соответствует CSS-псевдоклассу :invalid .
- rangeOverflow : Возвращает true , если значение больше указанного в атрибуте max максимума, и false если меньше или равно ему. Если true, элемент соответствует CSS-псевдоклассам :invalid и :out-of-range
- rangeUnderflow : Возвращает true , если значение меньше указанного в атрибуте min , и false если больше или равно ему. Если true, элемент соответствует CSS-псевдоклассу :invalid и :out-of-range .
- typeMismatch : Возвращает true , если значение не соответствует требуемому синтаксису (когда для type задано значение email или url ), и false если синтаксис корректный. Если true , элемент соответствует CSS-псевдоклассу :invalid .
- valid : Возвращает true , если элемент соответствует всем ограничениям валидации — следовательно, считается валидным, и false если не соответствует какому-то ограничению. Если true, элемент соответствует CSS-псевдоклассу :valid ; иначе :invalid .
- valueMissing : Возвращает true , если у элемента есть атрибут required , но не введено значенение, иначе возвращает false . Если true, элемент соответствует CSS-псевдоклассу :invalid .
- willValidate : Возвращает true , если элемент будет участвовать в валидации при отправке формы; иначе возвращает false .
Также для перечисленных выше элементов Constraint Validation API делает доступными следующие методы.
- checkValidity() : Возвращает true , если значение элемента проходит валидацию, иначе возвращает false . Если элемент не валиден, данный метод также запускает на нём событие invalid .
- setCustomValidity(message) : Позволяет добавить в элемент кастомное сообщение об ошибке; при этом элемент будет считаться не валидным и отобразится указанная ошибка. Это позволяет использовать JavaScript-код, чтобы представить ошибку валидации иначе, чем это предусмотрено стандартными средствами валидации HTML5. При сообщении об ошибке данное кастомное сообщение показывается пользователю.
Реализация кастомного сообщения об ошибке
Как вы видели в примерах HTML5-валидации выше, каждый раз, когда пользователь пытается отправить не валидную форму, браузер отображает сообщение об ошибке. Способ отображения сообщения зависит от браузера.
У этих автоматических сообщений есть два недостатка:
- Не существует стандартного способа их стилизации с помощью CSS.
- Они зависят от локали браузера, из-за чего страница может быть на одном языке, а сообщение об ошибке — на другом, как показано на следующем скриншоте браузера Firefox.
Настройка таких сообщений об ошибках является одной из наиболее распространённых причин использования Constraint Validation API. Давайте рассмотрим простой пример, как это делается.
Начнём с простого HTML (Не стесняйтесь поместить это в пустой HTML-файл. Вы можете взять за основу свежую копию fruit-start.html, если хотите):
Добавьте на страницу следующий JavaScript:
Здесь мы сохраняем ссылку на поле email, а затем добавляем к нему обработчик события, который запускает код обработчика каждый раз, когда в поле меняется значение.
В коде обработчика мы проверяем, возвращает ли свойство поля email validity.typeMismatch значение true , что значит, что содержащееся значение не соответствует шаблону корректного email-адреса. Если возвращается true , мы вызываем метод setCustomValidity() (en-US) с кастомным сообщением. Это делает поле не валидным, поэтому попытка отправить форму приводит к ошибке и отображается кастомное сообщение об ошибке.
Если свойство validity.typeMismatch возвращает false , мы вызываем метод setCustomValidity() с пустой строкой. Это делает поле валидным, поэтому форма может быть успешно отправлена.
Попробовать пример можно ниже:
Примечание:: Данный пример можно найти на GitHub по адресу custom-error-message.html (отдельно можно найти исходный код.)
Более подробный пример
Теперь, когда мы разобрали простой пример, давайте посмотрим, как можно использовать данный API для создания более сложной валидацию.
Во-первых, HTML. Опять же, не стесняйтесь писать его вместе с нами:
Эта простая форма использует атрибут novalidate , который отключает автоматическую валидацию браузером; это позволяет нашему скрипту взять управление валидацией на себя. Однако, это не отменяет поддержку Constraint Validation API или псевдоклассов, таких как :valid или ему подобных. Это значит, что хотя браузер автоматически и не проверяет валидность формы перед отправкой данных, вы можете сделать это самостоятельно и соответствующим образом стилизовать форму.
Объектом валидации является обязательный для заполнения , длина которого не должна быть меньше 8 символов. Давайте напишем код, проверяющий эти критерии, и покажем кастомное сообщение об ошибке в случае несоблюдения какого-то из них.
Мы хотим показывать сообщение об ошибке внутри элемента . Данному элементу задан атрибут aria-live , чтобы гарантировать, что наше кастомное сообщение об ошибке будет доступно всем, включая пользователей скринридеров.
Примечание: Ключевым моментом здесь является то, что добавление к форме атрибута novalidate отключает отображение встроенных сообщений об ошибке и позволяет вместо этого добавлять в DOM кастомные сообщения.
Перейдём к базовому CSS, чтобы немного улучшить внешний вид формы и обеспечить визуальную обратную связь при введении не валидных данных:
Теперь давайте рассмотрим JavaScript, который реализует кастомную валидацию.
Комментарии объясняют логику хорошо, но кратко:
- При каждом изменении значения поля, мы производим его валидацию. Если данные валидны, удаляем ранее отображаемые сообщения об ошибках. Если данные не валдны, запускаем showError() , чтобы показать соответствующую ошибку.
- При каждой попытке отправить форму, мы снова производим валидацию. Если данные валидны, позволяем отправку формы. Если данные не валидны, запускам showError() , чтобы показать соответствующее сообщение об ошибке, а также предотвращаем отправку формы с помощью preventDefault() .
- Функция showError() использует различные свойства объекта validity поля ввода, чтобы определить тип ошибки и отобразить соответсвущее сообщение.
Примечание: Рабочий пример можно найти на GitHub по адресу detailed-custom-validation.html (отдельно можно найти исходный код.)
Constraint Validation API явяется мощным инструментом валидации форм, позволяющим получить контроль над пользовательским интерфейсом, существенно превосходящий возможности HTML и CSS.
Примечание: Для получения дополнительной информации смотрите руководства Constraint validation guide (en-US) и Constraint Validation API.
Проверка форм без встроенного API
В некоторых случаях, например, при необходимости поддержки устаревших браузеров или кастомных элементов формы, вы не сможете или не захотите использовать Constraint Validation API. Вы по-прежнему сможете использовать JavaScript для валидации форм, но для этого всё нужно будет писать самостоятельно.
Для создания своего валидатора формы, задайте себе несколько вопросов:
Какую тип валидации я должен выполнить?
Вам нужно определить, как данные будут валидироваться: с помощью строковых операций, преобразования типов, регулярных выражений и так далее. Решать вам.
Что мне нужно делать, если форма не проходит валидацию?
Это явно вопрос пользовательского интерфейса. Вы должны решить, как в этом случае будет себя вести форма. Будет ли она в любом случае отправлять данные? Нужно ли выделять поля, содержащие ошибки? Нужно ли отображать сообщения об ошибках?
Как я могу помочь пользователю исправить не валидные данные?
Чтобы снизить степень разочарования пользователя, очень важно предоставить как можно больше полезной информации, чтобы помочь исправить данные, которые он ввёл неправильно. Нужно предложить правильные варианты, чтобы дать понять, какие данные вы ожидаете от него получить, а также сообщение, чётко описывающее ошибку. Если вы хотите подробнее ознакомиться с требованиями к пользовательскому интрефейсу при валидации форм, предлагаем прочитать следующие статьи:
Пример без использования Constraint Validation API
Чтобы проиллюстрировать это дальше приводится упрощённая версия предыдущего примера, которая работает с устаревшими браузерами.
HTML почти тот такой же; мы только удалили функционал валидации HTML5.
CSS также не требует особых изменений; мы только заменили CSS-псевдокласс :invalid на реальный класс и не использовали селектор по атрибутам, так как он не работает в Internet Explorer 6.
Существенно изменился только JavaScript-код, который теперь должен выполнять гораздо больше работы.
Результат выглядит следующим образом:
Как вы можете видеть, сделать собственную валидацию не так уж и сложно. Сложность состоит лишь в том, чтобы сделать его кроссплатформенным и работающим с любой формой, которую можно создать. Для проверки формы доступно множество библиотек, например Validate.js.
Проверьте свои навыки!
Вы дошли до конца этой статьи, но можете ли вы вспомнить самую важную информацию? Вы можете найти дополнительные тесты, чтобы убедиться, что вы сохранили эту информацию, прежде чем двигаться дальше — Test your skills: Form validation (en-US) .
Заключение
Для проверки формы на стороне клиента иногда требуется JavaScript, если вы хотите настроить стилизацию и сообщения об ошибках, но это всегда требует от вас внимательного отношения к пользователю. Всегда помните о необходимости помогать пользователям исправлять данные, которые они вводят. Для этого обязательно нужно:
- Отображать явные сообщения об ошибках.
- Снисходительно относиться к формату ввода.
- Указывать, где именно возникла ошибка. Особенно в больших формах.
После того, как вы убедились, что форма заполнена правильно, ее можно отправлять. Дальше мы рассмотрим отправку данных формы.
Источник
Use: setCustomValidity
First function sets custom error message:
$(function(){
$("input[name=Password]")[0].oninvalid = function () {
this.setCustomValidity("Please enter at least 5 characters.");
};
});
Second function turns off custom message. Without this function custom error message won’t turn off as the default message would:
$(function(){
$("input[name=Password]")[0].oninput= function () {
this.setCustomValidity("");
};
});
P.S. you can use oninput for all input types that have a text input.
For input type="checkbox"
you can use onclick to trigger when error should turnoff:
$(function(){
$("input[name=CheckBox]")[0].onclick= function () {
this.setCustomValidity("");
};
});
For input type="file"
you should use change.
The rest of the code inside change function is to check whether the file input is not empty.
P.S. This empty file check is for one file only, feel free to use any file checking method you like as well as you can check whether the file type is to your likes.
Function for file input custom message handling:
$("input[name=File]").change(function () {
let file = $("input[name=File]")[0].files[0];
if(this.files.length){
this.setCustomValidity("");
}
else {
this.setCustomValidity("You forgot to add your file...");
}
//this is for people who would like to know how to check file type
function FileType(filename) {
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
}
if(FileType(file.name)!="pdf"||FileType(file.name)!="PDF"){
this.setCustomValidity("Your file type has to be PDF");
//this is for people who would like to check if file size meets requirements
else if(file.size/1048576>2){
// file.size divided by 1048576 makes file size units MB file.size to megabytes
this.setCustomValidity("File hast to be less than 2MB");
}
else{
this.setCustomValidity("");
}
});//file input custom message handling function
HTML5 form required attribute. Set custom validation message?
JSFiddle: http://jsfiddle.net/yT3w3/
Non-JQuery solution:
function attachHandler(el, evtname, fn) {
if (el.addEventListener) {
el.addEventListener(evtname, fn.bind(el), false);
} else if (el.attachEvent) {
el.attachEvent('on' + evtname, fn.bind(el));
}
}
attachHandler(window, "load", function(){
var ele = document.querySelector("input[name=Password]");
attachHandler(ele, "invalid", function () {
this.setCustomValidity("Please enter at least 5 characters.");
this.setCustomValidity("");
});
});
JSFiddle: http://jsfiddle.net/yT3w3/2/
Валидация форм на стороне клиента
- Назад (en-US)
- Обзор: Forms
- Далее
Перед отправкой данных на сервер важно убедиться, что все обязательные поля формы заполнены данными в корректном формате. Это называется валидацией на стороне клиента и помогает убедиться, что данные, введённые в каждый элемент формы, соответствуют требованиям. Данная статья проведёт вас через основные концепци и примеры валидации на стороне клиента.
Начальные требования: | Владение компьютером, достаточное понимание HTML, CSS, и JavaScript. |
---|---|
Цель: | Понять, что такое валидация на стороне клиента, почему это важно и как применять различные техники для её реализации. |
Валидация на стороне клиента — это первичная проверка введённых данных, которая существенно улучшает удобство взаимодействия с интерфейсом; обнаружение некорректных данных на стороне клиента позволяет пользователю немедленно их исправить. Если же проверка происходит только на сервере, процесс заполнения может быть более трудоёмким, так как требует повторения одних и тех же действий отправки данных на сервер для получения обратного ответа с сообщением о том, что нужно исправить.
Однако, не следует рассматривать валидацию на стороне клиента как достаточную меру безопасности! Любые данные, отправляемые через форму, необходимо дополнительно проверять на безопасность и на стороне сервера, поскольку валидацию на стороне клиента достаточно просто обойти и она может не остановить злоумышленников. Чтобы лучше понимать потенциальные угрозы, рекомендуем ознакомиться с разделом Безопасность вебсайтов; валидация на стороне сервера выходит за рамки этого модуля, но о ней следует помнить.
Что такое валидация формы?
Зайдите на любой популярный сайт, имеющий форму регистрации. Вы заметите, что при вводе данных в неправильном формате, пользователя сразу уведомляют о наличии проблемы. Вы получите примерно такое сообщение:
- «Обязательное поле» (Вы не можете оставить поле пустым).
- «Пожалуйста, введите номер телефона в формате xxx-xxxx» (Чтобы данные считались корректными, их необходимо указать в определённом формате).
- «Пожалуйста, введите корректный email-адрес» (вы ввели данные в неправильном формате).
- «Длина пароля должна быть от 8 до 30 символов и включать одну заглавную букву, один символ, и одну цифру.» (Требования к формату данных достаточно конкретные).
Это называется валидацией формы. По мере ввода, браузер и/или сервер проверяют данные, чтобы определить, соответствуют ли они требуемому формату. Валидация, выполняемая в браузере, называется валидацией на стороне клиента, а выполняемая на сервере — валидацией на стороне сервера. В этом разделе мы сосредоточимся на валидации, выполняемой на стороне клиента.
Если формат корректен, приложение позволяет отправить данные на сервер и (обычно) сохранить в базу данных; в противном случае выводится сообщение с описанием того, что нужно исправить, позволяя ввести данные снова.
Мы хотим максимально упростить заполнение веб-форм. Тогда почему мы настаиваем валидации данных? На это есть три основные причины:
- Мы хотим получать правильные данные в правильном формате. Наши приложения не будут работать должным образом, если данные от пользователей хранятся в неправильном формате, некорректны сами по себе или вовсе пропущены.
- Мы хотим защитить данные пользователей. Принуждение пользователей вводить надёжные пароли облегчает защиту их аккаунтов.
- Мы хотим защитить себя. Существует множество способов, позволяющих злоумышленникам с помощью незащищённых форм навредить приложению (смотрите Безопасность вебсайтов).
Предупреждение: Никогда не доверяйте данным, передаваемым на сервер клиентской программой. Даже если ваша форма правильно валидируется и не допустит введение потенциально вредоносных данных на стороне клиента, злоумышленники по-прежнему могут изменить сетевой запрос.
Типы валидации на стороне клиента
Существует два типа валидации на стороне клиента, с которыми вы столкнётесь в Интернете:
- Встроенная валидация форм использует функционал валидации HTML5, который мы неоднократно обсуждали в этом модуле. HTML5-валидация обычно не требует большого количества JavaScript-кода и демонстрирует лучшую производительность, но не настолько настраиваема, как валидация с помощью JavaScript.
- JavaScript-валидация кодируется с помощью JavaScript. Она полностью настраиваема, но требует программирования всей логики (или использования библиотеки).
Использование встроенной валидации форм
Одной из самых важных функций элементов форм HTML5 (en-US) является способность валидировать бóльшую часть пользовательских данных без использования JavaScript. Это выполняется с помощью атрибутов валидации у элементов формы. Многие из них мы уже рассмотрели в этом курсе:
required
: Определяет, что для отправки формы данное поле предварительно должно быть заполнено.minlength
иmaxlength
: Задаёт минимальную и максимальную длину текстовых данных (строк)min
иmax
: Задаёт минимальное и максимальное значение для поля, расчитанного на числовой тип данныхtype
: Определяет тип данных, на который рассчитано поле: число, email-адрес или какой-то другой предустановленный типpattern
: С помощью регулярного выражения, определяет шаблон, которому должны соответствовать вводимые данные.
Если данные, введённые в поле формы, соответствуют правилам перечисленных выше атрибутов, они считаются валидными, если нет — не валидными
Когда элемент валиден, справедливы следующие утверждения:
- Элемент соответствует CSS-псевдоклассу
:valid
, позволяющему стилизовать только валидные элементы. - Если пользователь пытается отправить данные, браузер отправит форму при условии, что ничто другое (например, JavaScript) не помешает ему это сделать
Когда элемент не валиден, справедливы следующие утверждения:
- Элемент соответствует CSS-псевдоклассу
:invalid
или, в зависимости от ошибки, другим псевдоклассам (например,:out-of-range
), которые позволяют применять определённые стили к элементам, не являющимся валидными. - Если пользователь пытается отправить данные, браузер заблокирует форму и выведет сообщение об ошибке.
Примеры встроенной валидации форм
В этом разделе мы протестируем некоторые из атрибутов, которые обсуждали выше.
Простой начальный файл
Давайте начнём с простого примера: поле, позволяющее указать своё предпочтение — банан или вишня. Этот пример включает обычное текстовое поле <input>
, связанный с ним элемент <label>
и кнопку отправки формы <button>
. Исходный код можно найти на GitHub по адресу fruit-start.html, а ниже приведён рабочий пример.
<form>
<label for="choose">Would you prefer a banana or cherry?</label>
<input id="choose" name="i_like">
<button>Submit</button>
</form>
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
Для начала скопируйте файл fruit-start.html
в новую папку на вашем жёстком диске.
Атрибут required
Самым простым в HTML5-валидации является атрибут required
. Добавьте его к элементу, чтобы сделать заполнение обязательным. Элемент с данным атрибутом соответствует CSS-псевдоклассу :required
, а если поле ввода пустое, вместо отправки формы отобразится сообщение об ошибке. Пока поле пустое, оно также будет соответствовать CSS-псевдоклассу :invalid
.
Добавьте к полю атрибут required
, как показано ниже.
<form>
<label for="choose">Would you prefer a banana or cherry? (required)</label>
<input id="choose" name="i_like" required>
<button>Submit</button>
</form>
Обратите внимание на CSS, который включён в файл примера:
input:invalid {
border: 2px dashed red;
}
input:invalid:required {
background-image: linear-gradient(to right, pink, lightgreen);
}
input:valid {
border: 2px solid black;
}
Данный CSS задаёт полю красную пунктирную рамку, когда оно не валидно, а когда валидно — сплошную чёрную. Мы также добавили фоновый градиент для обязательных не валидных полей. Проверьте новое поведение в примере ниже:
Попробуйте отправить форму без введения значения. Обратите внимание, что не валидное поле получает фокус, появляется сообщение об ошибке («Заполните это поле») и блокируется отправка формы.
Наличие атрибута required
у любого элемента, который его поддерживает, означает, что элемент соответствует CSS-псевдоклассу :required
, независимо от того, имеет он значение или нет. Если элемент <input>
не содержит значение, он будет соответствовать псевдоклассу :invalid
.
Примечание: Для повышения удобства взаимодействия указывайте пользователям, какие поля являются обязательными. К тому же, этого требует руководство по обеспечению доступности WCAG. Требуйте обязательного ввода только тех данных, которые вам действительно нужны: например, так ли важно знать пол или должность пользователя?
Валидация с помощью регулярного выражения
Ещё одной полезной функцией валидации является атрибут pattern
, который в виде значения принимает Регулярное выражение. Регулярное выражение (regex) — это шаблон, который может быть использован для сопоставления набора символов в текстовой строке, поэтому они идеально подходят для валидации формы и используются для множества других целей в JavaScript.
Регулярные выражения достаточно сложны, и мы не будем подробно рассматривать эту тему в данной статье. Ниже приведены несколько примеров, чтобы дать вам представление о том, как они работают.
a
— Соответствует одному символуa
(неb
, неaa
, и так далее).abc
— Соответствует символуa
, за которой следуетb
, за которой следуетc
.ab?c
— Соответствует символуa
, за которым опционально может следоватьb
, за которым следуетc
. (ac
илиabc
)ab*c
— Соответствует символуa
, за которым опционально может следовать любое количество символовb
, за которыми следуетc
. (ac
,abc
,abbbbbc
, и так далее).a|b
— Соответствует символуa
илиb
.abc|xyz
— Соответствует в точностиabc
или в точностиxyz
(но неabcxyz
илиa
илиy
, и так далее).
Есть еще много возможностей, которые мы не упомянули. Полный список со множеством примеров можно найти в документации по Регулярным выражениям
Давайте рассмотрим пример. Добавьте в атрибут pattern
следующий шаблон:
<form>
<label for="choose">Would you prefer a banana or a cherry?</label>
<input id="choose" name="i_like" required pattern="[Bb]anana|[Cc]herry">
<button>Submit</button>
</form>
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
Это даёт нам следующее обновление — опробуйте его:
В этом примере элемент <input>
принимает одно из четырёх возможных значений: строку «banana», «Banana», «cherry», или «Cherry». Регулярные выражения чувствительны к регистру, но с помощью шаблона «Aa», вложенного в квадратные скобки, мы сделали поддержку написания слова как с большой, так и с маленькой буквы.
Подставьте в атрибут pattern
приведённые выше примеры регулярных выражений, и посмотрите, как это повлияет на валидацию введённого в поле значения. Попробуйте написать свои шаблоны проверки и посмотрите, что получится. По возможности, делайте их связанными с фруктами, чтобы примеры имели смысл.
Если не пустое значение элемента <input>
не соответствует шаблону регулярного выражения, input
будет соответствовать псевдоклассу :invalid
.
Примечание: Некоторым типам элементов <input>
для валидации с помощью регулярного выражения не требуется атрибут pattern
. Например, поле с типом email
валидирует значение по шаблону одного email-адреса или, если присутствует атрибут multiple
(en-US), шаблону списка email-адресов, разделённых запятыми.
Ограничение длины вводимых значений
Можно ограничить максимально допустимое количество символов для текстовых полей <input>
или <textarea>
(en-US) используя атрибуты minlength
(en-US) и maxlength
. Поле будет не валидным, если количество символов его содержимого будет меньше minlength
(en-US) или больше maxlength
.
Зачастую браузеры не позволяют пользователям вводить в текстовое поле значение, длина которого превышает максимально допустимую. Можно существенно повысить удобство использования, если помимо ограничения в атрибуте maxlength
добавить доступный индикатор, отображающий текущее и максимально допустимое количество символов, что даст пользователю возможность уместить содержимое в заданные рамки. Хорошим примером является окно написания твита в Twitter. Для реализации такого функционала можно использовать JavaScript, включая решения, использующие maxlength
.
Ограничение допустимых значений
В полях, предназначенных для ввода чисел (например, <input type="number">
), диапазон допустимых значений можно определить с помощью атрибутов min
и max
. Если поле содержит значение за пределами данного диапазона, оно будет не валидным.
Давайте рассмотрим другой пример. Создайте новую копию файла fruit-start.html.
Содержимое элемента <body>
замените на:
<form>
<div>
<label for="choose">Would you prefer a banana or a cherry?</label>
<input type="text" id="choose" name="i_like" required minlength="6" maxlength="6">
</div>
<div>
<label for="number">How many would you like?</label>
<input type="number" id="number" name="amount" value="1" min="1" max="10">
</div>
<div>
<button>Submit</button>
</div>
</form>
- Здесь мы в поле с типом
text
атрибутамminlength
иmaxlength
, задали одинаковое значение 6, что соответствует количеству символов в словах banana и cherry. - В поле с типом
number
атрибутуmin
мы задали значение 1, а атрибутуmax
значение 10. При вводе чисел за пределами данного диапазона, поле будет становиться не валидным; с помощью стрелок увеличения/уменьшения пользователи не смогут выйти за границы диапазона. Текущее поле не является обязательным для заполнения, поэтому даже после очистки будет оставаться валидным.
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
div {
margin-bottom: 10px;
}
Демонстрационный пример:
Примечание: <input type="number">
(и другие типы, такие как range
и date
) могут также принимать атрибут step
(en-US), который задаёт шаг увеличения или уменьшения значения при использовании кнопок вверх и вниз. В примере выше мы явно не указывали атрибут step
, поэтому он получает значение по умолчанию, равное 1
. Это значит, что дробные числа, такие как 3.2, будут не валидными.
Полный пример
Ниже представлен полный пример, демонстрирующий использование встроенного функционала валидации. Сначала немного HTML:
<form>
<p>
<fieldset>
<legend>Do you have a driver's license?<abbr title="This field is mandatory" aria-label="required">*</abbr></legend>
<!-- Так как в группе радио-кнопок, имеющих одинаковое имя, выбранной может быть
только одна, то и атрибут "required" достаточно задать хотя бы одной кнопке,
чтобы сделать всю группу обязательной для заполнения -->
<input type="radio" required name="driver" id="r1" value="yes"><label for="r1">Yes</label>
<input type="radio" required name="driver" id="r2" value="no"><label for="r2">No</label>
</fieldset>
</p>
<p>
<label for="n1">How old are you?</label>
<!-- Атрибут "pattern" может выступать фолбэком для браузеров, которые
не поддерживают поля ввода c числовым типом данных. Те браузеры,
которые такие поля поддерживают, будут просто игнорировать его.
Как раз, ниже атрибут "pattern" выполняет роль фолбека.
-->
<input type="number" min="12" max="120" step="1" id="n1" name="age"
pattern="d+">
</p>
<p>
<label for="t1">What's your favorite fruit?<abbr title="This field is mandatory" aria-label="required">*</abbr></label>
<input type="text" id="t1" name="fruit" list="l1" required
pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range">
<datalist id="l1">
<option>Banana</option>
<option>Cherry</option>
<option>Apple</option>
<option>Strawberry</option>
<option>Lemon</option>
<option>Orange</option>
</datalist>
</p>
<p>
<label for="t2">What's your e-mail address?</label>
<input type="email" id="t2" name="email">
</p>
<p>
<label for="t3">Leave a short message</label>
<textarea id="t3" name="msg" maxlength="140" rows="5"></textarea>
</p>
<p>
<button>Submit</button>
</p>
</form>
И немного CSS для стилизации HTML:
form {
font: 1em sans-serif;
max-width: 320px;
}
p > label {
display: block;
}
input[type="text"],
input[type="email"],
input[type="number"],
textarea,
fieldset {
width : 100%;
border: 1px solid #333;
box-sizing: border-box;
}
input:invalid {
box-shadow: 0 0 5px 1px red;
}
input:focus:invalid {
box-shadow: none;
}
Получим следующее:
В статье Атрибуты валидации (en-US) можно найти полный список атрибутов, которые можно использовать для ограничения допустимых значений ввода и типов полей input
, которые их поддерживают.
Валидация форм с помощью JavaScript
Если нужно управлять внешним видом встроенных сообщений об ошибке или работать с устаревшими браузерами, которые не поддерживают встроенную валидацию форм HTML, вам следует использовать JavaScript. В данном разделе мы рассмотрим различные способы делать это.
Constraint Validation API
Большинство браузеров поддерживают Constraint Validation API, который состоит из набора свойств и методов, доступных на DOM-интерфейсах следующих элементов форм:
HTMLButtonElement
(представляет элемент<button>
)HTMLFieldSetElement
(представляет элемент<fieldset>
)HTMLInputElement
(представляет элемент<input>
)HTMLOutputElement
(представляет элемент<output>
)HTMLSelectElement
(представляет элемент<select>
)HTMLTextAreaElement
(представляет элемент<textarea>
)
Для перечисленных выше элементов Constraint Validation API делает доступными следующие свойства.
validationMessage
: Возвращает локализованное сообщение, описывающее ограничения валидации (если таковые имеются), которым не удовлетворяет определённый элемент. Если элемент не участвует в валидации (willValidate
установлено вfalse
) или значение элемента удовлетворяет установленным ограничениям (является валидным), будет возвращена пустая строка.validity
: Возвращает объектValidityState
, который содержит несколько свойств, описывающих состояние валидности элемента. Подробное описание всех свойств доступности можно найти на странице справочникаValidityState
; ниже приведён список наиболее используемых:patternMismatch
: Возвращаетtrue
, если значение не соответствует шаблону, указанному в атрибутеpattern
, иfalse
если соответствует. Если true, элемент соответствует CSS-псевдоклассу:invalid
.tooLong
: Возвращаетtrue
, если значение длиннее максимальной длины, указанной в атрибутеmaxlength
, иfalse
если оно короче или равно ей. Если true, элемент соответствует CSS-псевдоклассу:invalid
.tooShort
: Возвращаетtrue
, если значение короче минимальной длины, указанной в атрибутеminlength
, иfalse
если оно длинее или равно ей. Если true, элемент соответствует CSS-псевдоклассу:invalid
.rangeOverflow
: Возвращаетtrue
, если значение больше указанного в атрибутеmax
максимума, иfalse
если меньше или равно ему. Если true, элемент соответствует CSS-псевдоклассам:invalid
и:out-of-range
rangeUnderflow
: Возвращаетtrue
, если значение меньше указанного в атрибутеmin
, иfalse
если больше или равно ему. Если true, элемент соответствует CSS-псевдоклассу:invalid
и:out-of-range
.typeMismatch
: Возвращаетtrue
, если значение не соответствует требуемому синтаксису (когда дляtype
задано значениеemail
илиurl
), иfalse
если синтаксис корректный. Еслиtrue
, элемент соответствует CSS-псевдоклассу:invalid
.valid
: Возвращаетtrue
, если элемент соответствует всем ограничениям валидации — следовательно, считается валидным, иfalse
если не соответствует какому-то ограничению. Если true, элемент соответствует CSS-псевдоклассу:valid
; иначе:invalid
.valueMissing
: Возвращаетtrue
, если у элемента есть атрибутrequired
, но не введено значенение, иначе возвращаетfalse
. Если true, элемент соответствует CSS-псевдоклассу:invalid
.
willValidate
: Возвращаетtrue
, если элемент будет участвовать в валидации при отправке формы; иначе возвращаетfalse
.
Также для перечисленных выше элементов Constraint Validation API делает доступными следующие методы.
checkValidity()
: Возвращаетtrue
, если значение элемента проходит валидацию, иначе возвращаетfalse
. Если элемент не валиден, данный метод также запускает на нём событиеinvalid
.setCustomValidity(message)
: Позволяет добавить в элемент кастомное сообщение об ошибке; при этом элемент будет считаться не валидным и отобразится указанная ошибка. Это позволяет использовать JavaScript-код, чтобы представить ошибку валидации иначе, чем это предусмотрено стандартными средствами валидации HTML5. При сообщении об ошибке данное кастомное сообщение показывается пользователю.
Реализация кастомного сообщения об ошибке
Как вы видели в примерах HTML5-валидации выше, каждый раз, когда пользователь пытается отправить не валидную форму, браузер отображает сообщение об ошибке. Способ отображения сообщения зависит от браузера.
У этих автоматических сообщений есть два недостатка:
- Не существует стандартного способа их стилизации с помощью CSS.
- Они зависят от локали браузера, из-за чего страница может быть на одном языке, а сообщение об ошибке — на другом, как показано на следующем скриншоте браузера Firefox.
Настройка таких сообщений об ошибках является одной из наиболее распространённых причин использования Constraint Validation API. Давайте рассмотрим простой пример, как это делается.
Начнём с простого HTML (Не стесняйтесь поместить это в пустой HTML-файл. Вы можете взять за основу свежую копию fruit-start.html, если хотите):
<form>
<label for="mail">I would like you to provide me with an e-mail address:</label>
<input type="email" id="mail" name="mail">
<button>Submit</button>
</form>
Добавьте на страницу следующий JavaScript:
const email = document.getElementById("mail");
email.addEventListener("input", function (event) {
if (email.validity.typeMismatch) {
email.setCustomValidity("I am expecting an e-mail address!");
} else {
email.setCustomValidity("");
}
});
Здесь мы сохраняем ссылку на поле email, а затем добавляем к нему обработчик события, который запускает код обработчика каждый раз, когда в поле меняется значение.
В коде обработчика мы проверяем, возвращает ли свойство поля email validity.typeMismatch
значение true
, что значит, что содержащееся значение не соответствует шаблону корректного email-адреса. Если возвращается true
, мы вызываем метод setCustomValidity()
(en-US) с кастомным сообщением. Это делает поле не валидным, поэтому попытка отправить форму приводит к ошибке и отображается кастомное сообщение об ошибке.
Если свойство validity.typeMismatch
возвращает false
, мы вызываем метод setCustomValidity()
с пустой строкой. Это делает поле валидным, поэтому форма может быть успешно отправлена.
Попробовать пример можно ниже:
Более подробный пример
Теперь, когда мы разобрали простой пример, давайте посмотрим, как можно использовать данный API для создания более сложной валидацию.
Во-первых, HTML. Опять же, не стесняйтесь писать его вместе с нами:
<form novalidate>
<p>
<label for="mail">
<span>Please enter an email address:</span>
<input type="email" id="mail" name="mail" required minlength="8">
<span class="error" aria-live="polite"></span>
</label>
</p>
<button>Submit</button>
</form>
Эта простая форма использует атрибут novalidate
, который отключает автоматическую валидацию браузером; это позволяет нашему скрипту взять управление валидацией на себя. Однако, это не отменяет поддержку Constraint Validation API или псевдоклассов, таких как :valid
или ему подобных. Это значит, что хотя браузер автоматически и не проверяет валидность формы перед отправкой данных, вы можете сделать это самостоятельно и соответствующим образом стилизовать форму.
Объектом валидации является обязательный для заполнения <input type="email">
, длина которого не должна быть меньше 8 символов. Давайте напишем код, проверяющий эти критерии, и покажем кастомное сообщение об ошибке в случае несоблюдения какого-то из них.
Мы хотим показывать сообщение об ошибке внутри элемента <span>
. Данному элементу задан атрибут aria-live
, чтобы гарантировать, что наше кастомное сообщение об ошибке будет доступно всем, включая пользователей скринридеров.
Примечание: Ключевым моментом здесь является то, что добавление к форме атрибута novalidate
отключает отображение встроенных сообщений об ошибке и позволяет вместо этого добавлять в DOM кастомные сообщения.
Перейдём к базовому CSS, чтобы немного улучшить внешний вид формы и обеспечить визуальную обратную связь при введении не валидных данных:
body {
font: 1em sans-serif;
width: 200px;
padding: 0;
margin : 0 auto;
}
p * {
display: block;
}
input[type=email]{
-webkit-appearance: none;
appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
box-sizing: border-box;
}
/* Это стили для не валидных полей */
input:invalid{
border-color: #900;
background-color: #FDD;
}
input:focus:invalid {
outline: none;
}
/* Это стили для кастомных сообщений об ошибке */
.error {
width : 100%;
padding: 0;
font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
box-sizing: border-box;
}
.error.active {
padding: 0.3em;
}
Теперь давайте рассмотрим JavaScript, который реализует кастомную валидацию.
// Существуют разные способы получить DOM-узел; здесь мы определяем саму форму и
// поле ввода email и элемент span, в который поместим сообщение об ошибке
const form = document.getElementsByTagName('form')[0];
const email = document.getElementById('mail');
const emailError = document.querySelector('#mail + span.error');
email.addEventListener('input', function (event) {
// Каждый раз, когда пользователь что-то вводит,
// мы проверяем, являются ли поля формы валидными
if (email.validity.valid) {
// Если на момент валидации какое-то сообщение об ошибке уже отображается,
// если поле валидно, удаляем сообщение
emailError.textContent = ''; // Сбросить содержимое сообщения
emailError.className = 'error'; // Сбросить визуальное состояние сообщения
} else {
// Если поле не валидно, показываем правильную ошибку
showError();
}
});
form.addEventListener('submit', function (event) {
// Если поле email валдно, позволяем форме отправляться
if(!email.validity.valid) {
// Если поле email не валидно, отображаем соответствующее сообщение об ошибке
showError();
// Затем предотвращаем стандартное событие отправки формы
event.preventDefault();
}
});
function showError() {
if(email.validity.valueMissing) {
// Если поле пустое,
// отображаем следующее сообщение об ошибке
emailError.textContent = 'You need to enter an e-mail address.';
} else if(email.validity.typeMismatch) {
// Если поле содержит не email-адрес,
// отображаем следующее сообщение об ошибке
emailError.textContent = 'Entered value needs to be an e-mail address.';
} else if(email.validity.tooShort) {
// Если содержимое слишком короткое,
// отображаем следующее сообщение об ошибке
emailError.textContent = `Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
}
// Задаём соответствующую стилизацию
emailError.className = 'error active';
}
Комментарии объясняют логику хорошо, но кратко:
- При каждом изменении значения поля, мы производим его валидацию. Если данные валидны, удаляем ранее отображаемые сообщения об ошибках. Если данные не валдны, запускаем
showError()
, чтобы показать соответствующую ошибку. - При каждой попытке отправить форму, мы снова производим валидацию. Если данные валидны, позволяем отправку формы. Если данные не валидны, запускам
showError()
, чтобы показать соответствующее сообщение об ошибке, а также предотвращаем отправку формы с помощьюpreventDefault()
. - Функция
showError()
использует различные свойства объектаvalidity
поля ввода, чтобы определить тип ошибки и отобразить соответсвущее сообщение.
Рабочий пример:
Constraint Validation API явяется мощным инструментом валидации форм, позволяющим получить контроль над пользовательским интерфейсом, существенно превосходящий возможности HTML и CSS.
Проверка форм без встроенного API
В некоторых случаях, например, при необходимости поддержки устаревших браузеров или кастомных элементов формы, вы не сможете или не захотите использовать Constraint Validation API. Вы по-прежнему сможете использовать JavaScript для валидации форм, но для этого всё нужно будет писать самостоятельно.
Для создания своего валидатора формы, задайте себе несколько вопросов:
- Какую тип валидации я должен выполнить?
-
Вам нужно определить, как данные будут валидироваться: с помощью строковых операций, преобразования типов, регулярных выражений и так далее. Решать вам.
- Что мне нужно делать, если форма не проходит валидацию?
-
Это явно вопрос пользовательского интерфейса. Вы должны решить, как в этом случае будет себя вести форма. Будет ли она в любом случае отправлять данные? Нужно ли выделять поля, содержащие ошибки? Нужно ли отображать сообщения об ошибках?
- Как я могу помочь пользователю исправить не валидные данные?
-
Чтобы снизить степень разочарования пользователя, очень важно предоставить как можно больше полезной информации, чтобы помочь исправить данные, которые он ввёл неправильно. Нужно предложить правильные варианты, чтобы дать понять, какие данные вы ожидаете от него получить, а также сообщение, чётко описывающее ошибку. Если вы хотите подробнее ознакомиться с требованиями к пользовательскому интрефейсу при валидации форм, предлагаем прочитать следующие статьи:
- SmashingMagazine: Form-Field Validation: The Errors-Only Approach
- SmashingMagazine: Web Form Validation: Best Practices and Tutorials
- WebFX: 10 Tips for Optimizing Web Form Submission Usability
- A List Apart: Inline Validation in Web Forms
Пример без использования Constraint Validation API
Чтобы проиллюстрировать это дальше приводится упрощённая версия предыдущего примера, которая работает с устаревшими браузерами.
HTML почти тот такой же; мы только удалили функционал валидации HTML5.
<form>
<p>
<label for="mail">
<span>Please enter an email address:</span>
<input type="text" id="mail" name="mail">
<span class="error" aria-live="polite"></span>
</label>
</p>
<!-- Для некоторых устаревших браузеров элементу `button` нужно добавлять
атрибут `type` с явно заданным значением `submit` -->
<button type="submit">Submit</button>
</form>
CSS также не требует особых изменений; мы только заменили CSS-псевдокласс :invalid
на реальный класс и не использовали селектор по атрибутам, так как он не работает в Internet Explorer 6.
body {
font: 1em sans-serif;
width: 200px;
padding: 0;
margin : 0 auto;
}
form {
max-width: 200px;
}
p * {
display: block;
}
input.mail {
-webkit-appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
box-sizing: border-box;
}
/* Стилизация не валидных полей */
input.invalid{
border-color: #900;
background-color: #FDD;
}
input:focus.invalid {
outline: none;
}
/* Стилизация сообщений об ошибках */
.error {
width : 100%;
padding: 0;
font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
box-sizing: border-box;
}
.error.active {
padding: 0.3em;
}
Существенно изменился только JavaScript-код, который теперь должен выполнять гораздо больше работы.
// Устаревшие браузеры поддерживают несколько способов получения DOM-узла
const form = document.getElementsByTagName('form')[0];
const email = document.getElementById('mail');
// Ниже приведён способ получения узла следующего родственного DOM-элемента
// Он опасен, потому что можно создать бесконечный цикл.
// В современных браузерах лучше использовать `element.nextElementSibling`
let error = email;
while ((error = error.nextSibling).nodeType != 1);
// Согласно спецификации HTML5
const emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$/;
// Многие устаревшие браузеры не поддерживают метод `addEventListener`
// Есть простой способ заменить его; и далеко не единственный
function addEvent(element, event, callback) {
let previousEventCallBack = element["on"+event];
element["on"+event] = function (e) {
let output = callback(e);
// Колбэк, который возвращает `false`, останавливает цепочку колбэков
// и прерывает выполнение колбэка события
if (output === false) return false;
if (typeof previousEventCallBack === 'function') {
output = previousEventCallBack(e);
if(output === false) return false;
}
};
}
// Теперь мы можем изменить наши критерии валидации
// Поскольку мы не полагаемся на CSS-псевдокласс, для поля email
// нужно явно задать валидный / не валидный класс
addEvent(window, "load", function () {
// Проверка, является ли поле пустым (помните, оно не являтеся обязательным)
// Если поле не пустое, проверяем содержимое на соответствует шаблону email
const test = email.value.length === 0 || emailRegExp.test(email.value);
email.className = test ? "valid" : "invalid";
});
// Здесь определяется поведение при вводе пользователем значения поля
addEvent(email, "input", function () {
const test = email.value.length === 0 || emailRegExp.test(email.value);
if (test) {
email.className = "valid";
error.textContent = "";
error.className = "error";
} else {
email.className = "invalid";
}
});
// Здесь определяется поведение при попытке отправить данные
addEvent(form, "submit", function () {
const test = email.value.length === 0 || emailRegExp.test(email.value);
if (!test) {
email.className = "invalid";
error.textContent = "I expect an e-mail, darling!";
error.className = "error active";
// Некоторые устаревшие браузеры не поддерживают метод event.preventDefault()
return false;
} else {
email.className = "valid";
error.textContent = "";
error.className = "error";
}
});
Результат выглядит следующим образом:
Как вы можете видеть, сделать собственную валидацию не так уж и сложно. Сложность состоит лишь в том, чтобы сделать его кроссплатформенным и работающим с любой формой, которую можно создать. Для проверки формы доступно множество библиотек, например Validate.js.
Проверьте свои навыки!
Вы дошли до конца этой статьи, но можете ли вы вспомнить самую важную информацию? Вы можете найти дополнительные тесты, чтобы убедиться, что вы сохранили эту информацию, прежде чем двигаться дальше — Test your skills: Form validation (en-US).
Заключение
Для проверки формы на стороне клиента иногда требуется JavaScript, если вы хотите настроить стилизацию и сообщения об ошибках, но это всегда требует от вас внимательного отношения к пользователю. Всегда помните о необходимости помогать пользователям исправлять данные, которые они вводят. Для этого обязательно нужно:
- Отображать явные сообщения об ошибках.
- Снисходительно относиться к формату ввода.
- Указывать, где именно возникла ошибка. Особенно в больших формах.
После того, как вы убедились, что форма заполнена правильно, ее можно отправлять. Дальше мы рассмотрим отправку данных формы.
- Назад (en-US)
- Обзор: Forms
- Далее
In this module
Продвинутые темы
HTML5 Form Validation With the “pattern” Attribute
In this tutorial we’ll explore HTML’s pattern attribute, using it to help us customize the way we validate our forms.
Form Validation Video
Check out the video tutorial below, subscribe to Tuts+ on Youtube, or read on to learn more about HTML form validation and the pattern attribute!
HTML5 Form Validation
Form validation is of vital importance to a website’s security as well as its usability. The validation process evaluates whether the input value is in the correct format before submitting it. For example, if we have an input field for an email address, the value must certainly contain a valid email address; it should start with a letter or a number, followed by the @ symbol, then end with a domain name.
The HTML5 specification has made validation that bit easier with the introduction of new input types such as email , url , and tel , and these also come packaged up with predefined validation. Whenever the value given is not met with the expected formatting, these input types will throw an error message thus preventing submission.
Invalid email address error message (Chrome) thanks to HTML5 form validation
Expecting every possible input scenario to be catered for is impractical, however. What if you have a username, zip code, or any special data types that are not specified as standard input types? How do we validate those inputs? This is where the attribute pattern comes into play.
Using the Pattern Attribute
The pattern attribute is only applicable on the input element. It allows us to define our own rule to validate the input value using Regular Expressions (RegEx). Again, if the value does not match the specified pattern, the input will throw an error.
For example, say we have a username input in our form. There isn’t a standard type for username, hence we use the regular text input type:
Let’s define a rule to add using the pattern attribute. In this case, we’ll specify that the username should only consist of lowercase letters; no capital letters, numbers or other special characters allowed. In addition, the username length shouldn’t be more than 15 characters. In RegEx, this rule can be expressed as [a-z] <1,15>.
Add [a-z] <1,15>as the value of the pattern attribute in our username input:
Now, since it only accepts lowercase letters, submitting any other value will throw an error message:
The error message, stating the pattern is not matched
As you can see above, the error message says “Please match the requested format.” So our validation is working, but this message doesn’t help our users understand what the requested format actually is. UX fail.
Customizing the Validation Message
Fortunately, we can customize the message to be more helpful, and we have a couple of ways to do so. The easiest approach is to specify a title attribute within our input element:
Now the title is included along with the default message:
Still, the popup message is inconsistent. If we compare it with the one thrown by the email input type shown earlier, the actual instructions could be more prominent.
The second approach will solve this for us.
Replacing the Default HTML5 Validation Message
Let’s now replace the default “Please match the requested format” with a completely customized message. We’ll use a bit of JavaScript to do this.
Begin by adding an id to the input element, so as to be able to select it conveniently.
Now, we can select the input element using JavaScript and assign it to a variable (either between
Источник
Client-side form validation
Before submitting data to the server, it is important to ensure all required form controls are filled out, in the correct format. This is called client-side form validation, and helps ensure data submitted matches the requirements set forth in the various form controls. This article leads you through basic concepts and examples of client-side form validation.
Prerequisites: | Computer literacy, a reasonable understanding of HTML, CSS, and JavaScript. |
---|---|
Objective: | To understand what client-side form validation is, why it’s important, and how to apply various techniques to implement it. |
Client-side validation is an initial check and an important feature of good user experience; by catching invalid data on the client-side, the user can fix it straight away. If it gets to the server and is then rejected, a noticeable delay is caused by a round trip to the server and then back to the client-side to tell the user to fix their data.
However, client-side validation should not be considered an exhaustive security measure! Your apps should always perform security checks on any form-submitted data on the server-side as well as the client-side, because client-side validation is too easy to bypass, so malicious users can still easily send bad data through to your server. Read Website security for an idea of what could happen; implementing server-side validation is somewhat beyond the scope of this module, but you should bear it in mind.
What is form validation?
Go to any popular site with a registration form, and you will notice that they provide feedback when you don’t enter your data in the format they are expecting. You’ll get messages such as:
- «This field is required» (You can’t leave this field blank).
- «Please enter your phone number in the format xxx-xxxx» (A specific data format is required for it to be considered valid).
- «Please enter a valid email address» (the data you entered is not in the right format).
- «Your password needs to be between 8 and 30 characters long and contain one uppercase letter, one symbol, and a number.» (A very specific data format is required for your data).
This is called form validation. When you enter data, the browser and/or the web server will check to see that the data is in the correct format and within the constraints set by the application. Validation done in the browser is called client-side validation, while validation done on the server is called server-side validation. In this chapter we are focusing on client-side validation.
If the information is correctly formatted, the application allows the data to be submitted to the server and (usually) saved in a database; if the information isn’t correctly formatted, it gives the user an error message explaining what needs to be corrected, and lets them try again.
We want to make filling out web forms as easy as possible. So why do we insist on validating our forms? There are three main reasons:
- We want to get the right data, in the right format. Our applications won’t work properly if our users’ data is stored in the wrong format, is incorrect, or is omitted altogether.
- We want to protect our users’ data. Forcing our users to enter secure passwords makes it easier to protect their account information.
- We want to protect ourselves. There are many ways that malicious users can misuse unprotected forms to damage the application. See Website security.
Warning: Never trust data passed to your server from the client. Even if your form is validating correctly and preventing malformed input on the client-side, a malicious user can still alter the network request.
Different types of client-side validation
There are two different types of client-side validation that you’ll encounter on the web:
- Built-in form validation uses HTML form validation features, which we’ve discussed in many places throughout this module. This validation generally doesn’t require much JavaScript. Built-in form validation has better performance than JavaScript, but it is not as customizable as JavaScript validation.
- JavaScript validation is coded using JavaScript. This validation is completely customizable, but you need to create it all (or use a library).
Using built-in form validation
One of the most significant features of modern form controls is the ability to validate most user data without relying on JavaScript. This is done by using validation attributes on form elements. We’ve seen many of these earlier in the course, but to recap:
- required : Specifies whether a form field needs to be filled in before the form can be submitted.
- minlength and maxlength : Specifies the minimum and maximum length of textual data (strings).
- min and max : Specifies the minimum and maximum values of numerical input types.
- type : Specifies whether the data needs to be a number, an email address, or some other specific preset type.
- pattern : Specifies a regular expression that defines a pattern the entered data needs to follow.
If the data entered in a form field follows all of the rules specified by the above attributes, it is considered valid. If not, it is considered invalid.
When an element is valid, the following things are true:
- The element matches the :valid CSS pseudo-class, which lets you apply a specific style to valid elements.
- If the user tries to send the data, the browser will submit the form, provided there is nothing else stopping it from doing so (e.g., JavaScript).
When an element is invalid, the following things are true:
- The element matches the :invalid CSS pseudo-class, and sometimes other UI pseudo-classes (e.g., :out-of-range ) depending on the error, which lets you apply a specific style to invalid elements.
- If the user tries to send the data, the browser will block the form and display an error message.
Note: There are several errors that will prevent the form from being submitted, including a badInput , patternMismatch , rangeOverflow or rangeUnderflow , stepMismatch , tooLong or tooShort , typeMismatch , valueMissing , or a customError .
Built-in form validation examples
In this section, we’ll test out some of the attributes that we discussed above.
Simple start file
Let’s start with a simple example: an input that allows you to choose whether you prefer a banana or a cherry. This example involves a simple text with an associated and a submit . Find the source code on GitHub at fruit-start.html and a live example below.
To begin, make a copy of fruit-start.html in a new directory on your hard drive.
The required attribute
The simplest HTML validation feature is the required attribute. To make an input mandatory, add this attribute to the element. When this attribute is set, the element matches the :required UI pseudo-class and the form won’t submit, displaying an error message on submission when the input is empty. While empty, the input will also be considered invalid, matching the :invalid UI pseudo-class.
Add a required attribute to your input, as shown below.
Note the CSS that is included in the example file:
This CSS causes the input to have a red dashed border when it is invalid and a more subtle solid black border when valid. We also added a background gradient when the input is required and invalid. Try out the new behavior in the example below:
Note: You can find this example live on GitHub as fruit-validation.html. See also the source code.
Try submitting the form without a value. Note how the invalid input gets focus, a default error message («Please fill out this field») appears, and the form is prevented from being sent.
The presence of the required attribute on any element that supports this attribute means the element matches the :required pseudo-class whether it has a value or not. If the has no value, the input will match the :invalid pseudo-class.
Note: For good user experience, indicate to the user when form fields are required. It isn’t only good user experience, it is required by WCAG accessibility guidelines. Also, only require users to input data you actually need: For example, why do you really need to know someone’s gender or title?
Validating against a regular expression
Another useful validation feature is the pattern attribute, which expects a Regular Expression as its value. A regular expression (regex) is a pattern that can be used to match character combinations in text strings, so regexps are ideal for form validation and serve a variety of other uses in JavaScript.
Regexps are quite complex, and we don’t intend to teach you them exhaustively in this article. Below are some examples to give you a basic idea of how they work.
- a — Matches one character that is a (not b , not aa , and so on).
- abc — Matches a , followed by b , followed by c .
- ab?c — Matches a , optionally followed by a single b , followed by c . ( ac or abc )
- ab*c — Matches a , optionally followed by any number of b s, followed by c . ( ac , abc , abbbbbc , and so on).
- a|b — Matches one character that is a or b .
- abc|xyz — Matches exactly abc or exactly xyz (but not abcxyz or a or y , and so on).
There are many more possibilities that we don’t cover here. For a complete list and many examples, consult our Regular expressions documentation.
Let’s implement an example. Update your HTML to add a pattern attribute like this:
This gives us the following update — try it out:
Note: You can find this example live on GitHub as fruit-pattern.html (see also the source code.)
In this example, the element accepts one of four possible values: the strings «banana», «Banana», «cherry», or «Cherry». Regular expressions are case-sensitive, but we’ve made it support capitalized as well as lower-case versions using an extra «Aa» pattern nested inside square brackets.
At this point, try changing the value inside the pattern attribute to equal some of the examples you saw earlier, and look at how that affects the values you can enter to make the input value valid. Try writing some of your own, and see how it goes. Make them fruit-related where possible so that your examples make sense!
If a non-empty value of the doesn’t match the regular expression’s pattern, the input will match the :invalid pseudo-class.
Note: Some element types don’t need a pattern attribute to be validated against a regular expression. Specifying the email type, for example, validates the inputs value against a well-formed email address pattern or a pattern matching a comma-separated list of email addresses if it has the multiple attribute.
Note: The
element doesn’t support the pattern attribute.
Constraining the length of your entries
You can constrain the character length of all text fields created by or
by using the minlength and maxlength attributes. A field is invalid if it has a value and that value has fewer characters than the minlength value or more than the maxlength value.
Browsers often don’t let the user type a longer value than expected into text fields. A better user experience than just using maxlength is to also provide character count feedback in an accessible manner and let them edit their content down to size. An example of this is the character limit seen on Twitter when Tweeting. JavaScript, including solutions using maxlength , can be used to provide this.
Constraining the values of your entries
For number fields (i.e. ), the min and max attributes can be used to provide a range of valid values. If the field contains a value outside this range, it will be invalid.
Let’s look at another example. Create a new copy of the fruit-start.html file.
Now delete the contents of the element, and replace it with the following:
- Here you’ll see that we’ve given the text field a minlength and maxlength of six, which is the same length as banana and cherry.
- We’ve also given the number field a min of one and a max of ten. Entered numbers outside this range will show as invalid; users won’t be able to use the increment/decrement arrows to move the value outside of this range. If the user manually enters a number outside of this range, the data is invalid. The number is not required, so removing the value will still result in a valid value.
Here is the example running live:
Note: You can find this example live on GitHub as fruit-length.html. See also the source code.
Note: (and other types, such as range and date ) can also take a step attribute, which specifies what increment the value will go up or down by when the input controls are used (such as the up and down number buttons). In the above example we’ve not included a step attribute, so the value defaults to 1 . This means that floats, like 3.2, will also show as invalid.
Full example
Here is a full example to show usage of HTML’s built-in validation features. First, some HTML:
And now some CSS to style the HTML:
This renders as follows:
See Validation-related attributes for a complete list of attributes that can be used to constrain input values and the input types that support them.
Note: You can find this example live on GitHub as full-example.html (see also the source code.)
Validating forms using JavaScript
You must use JavaScript if you want to take control over the look and feel of native error messages. In this section we will look at the different ways to do this.
The Constraint Validation API
The Constraint Validation API consists of a set of methods and properties available on the following form element DOM interfaces:
The Constraint Validation API makes the following properties available on the above elements.
- validationMessage : Returns a localized message describing the validation constraints that the control doesn’t satisfy (if any). If the control is not a candidate for constraint validation ( willValidate is false ) or the element’s value satisfies its constraints (is valid), this will return an empty string.
- validity : Returns a ValidityState object that contains several properties describing the validity state of the element. You can find full details of all the available properties in the ValidityState reference page; below is listed a few of the more common ones:
- patternMismatch : Returns true if the value does not match the specified pattern , and false if it does match. If true, the element matches the :invalid CSS pseudo-class.
- tooLong : Returns true if the value is longer than the maximum length specified by the maxlength attribute, or false if it is shorter than or equal to the maximum. If true, the element matches the :invalid CSS pseudo-class.
- tooShort : Returns true if the value is shorter than the minimum length specified by the minlength attribute, or false if it is greater than or equal to the minimum. If true, the element matches the :invalid CSS pseudo-class.
- rangeOverflow : Returns true if the value is greater than the maximum specified by the max attribute, or false if it is less than or equal to the maximum. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
- rangeUnderflow : Returns true if the value is less than the minimum specified by the min attribute, or false if it is greater than or equal to the minimum. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
- typeMismatch : Returns true if the value is not in the required syntax (when type is email or url ), or false if the syntax is correct. If true , the element matches the :invalid CSS pseudo-class.
- valid : Returns true if the element meets all its validation constraints, and is therefore considered to be valid, or false if it fails any constraint. If true, the element matches the :valid CSS pseudo-class; the :invalid CSS pseudo-class otherwise.
- valueMissing : Returns true if the element has a required attribute, but no value, or false otherwise. If true, the element matches the :invalid CSS pseudo-class.
- willValidate : Returns true if the element will be validated when the form is submitted; false otherwise.
The Constraint Validation API also makes the following methods available on the above elements and the form element.
- checkValidity() : Returns true if the element’s value has no validity problems; false otherwise. If the element is invalid, this method also fires an invalid event on the element.
- reportValidity() : Reports invalid field(s) using events. This method is useful in combination with preventDefault() in an onSubmit event handler.
- setCustomValidity(message) : Adds a custom error message to the element; if you set a custom error message, the element is considered to be invalid, and the specified error is displayed. This lets you use JavaScript code to establish a validation failure other than those offered by the standard HTML validation constraints. The message is shown to the user when reporting the problem.
Implementing a customized error message
As you saw in the HTML validation constraint examples earlier, each time a user tries to submit an invalid form, the browser displays an error message. The way this message is displayed depends on the browser.
These automated messages have two drawbacks:
- There is no standard way to change their look and feel with CSS.
- They depend on the browser locale, which means that you can have a page in one language but an error message displayed in another language, as seen in the following Firefox screenshot.
Customizing these error messages is one of the most common use cases of the Constraint Validation API. Let’s work through a simple example of how to do this.
We’ll start with some simple HTML (feel free to put this in a blank HTML file; use a fresh copy of fruit-start.html as a basis, if you like):
And add the following JavaScript to the page:
Here we store a reference to the email input, then add an event listener to it that runs the contained code each time the value inside the input is changed.
Inside the contained code, we check whether the email input’s validity.typeMismatch property returns true , meaning that the contained value doesn’t match the pattern for a well-formed email address. If so, we call the setCustomValidity() method with a custom message. This renders the input invalid, so that when you try to submit the form, submission fails and the custom error message is displayed.
If the validity.typeMismatch property returns false , we call the setCustomValidity() method with an empty string. This renders the input valid, so the form will submit.
You can try it out below:
Note: You can find this example live on GitHub as custom-error-message.html (see also the source code.)
A more detailed example
Now that we’ve seen a really simple example, let’s see how we can use this API to build some slightly more complex custom validation.
First, the HTML. Again, feel free to build this along with us:
This simple form uses the novalidate attribute to turn off the browser’s automatic validation; this lets our script take control over validation. However, this doesn’t disable support for the constraint validation API nor the application of CSS pseudo-classes like :valid , etc. That means that even though the browser doesn’t automatically check the validity of the form before sending its data, you can still do it yourself and style the form accordingly.
Our input to validate is an , which is required , and has a minlength of 8 characters. Let’s check these using our own code, and show a custom error message for each one.
We are aiming to show the error messages inside a element. The aria-live attribute is set on that to make sure that our custom error message will be presented to everyone, including it being read out to screen reader users.
Note: A key point here is that setting the novalidate attribute on the form is what stops the form from showing its own error message bubbles, and allows us to instead display the custom error messages in the DOM in some manner of our own choosing.
Now onto some basic CSS to improve the look of the form slightly, and provide some visual feedback when the input data is invalid:
Now let’s look at the JavaScript that implements the custom error validation.
The comments explain things pretty well, but briefly:
- Every time we change the value of the input, we check to see if it contains valid data. If it has then we remove any error message being shown. If the data is not valid, we run showError() to show the appropriate error.
- Every time we try to submit the form, we again check to see if the data is valid. If so, we let the form submit. If not, we run showError() to show the appropriate error, and stop the form submitting with preventDefault() .
- The showError() function uses various properties of the input’s validity object to determine what the error is, and then displays an error message as appropriate.
Here is the live result:
Note: You can find this example live on GitHub as detailed-custom-validation.html. See also the source code.
The constraint validation API gives you a powerful tool to handle form validation, letting you have enormous control over the user interface above and beyond what you can do with HTML and CSS alone.
Validating forms without a built-in API
In some cases, such as custom controls, you won’t be able to or won’t want to use the Constraint Validation API. You’re still able to use JavaScript to validate your form, but you’ll just have to write your own.
To validate a form, ask yourself a few questions:
What kind of validation should I perform?
You need to determine how to validate your data: string operations, type conversion, regular expressions, and so on. It’s up to you.
What should I do if the form doesn’t validate?
This is clearly a UI matter. You have to decide how the form will behave. Does the form send the data anyway? Should you highlight the fields that are in error? Should you display error messages?
How can I help the user to correct invalid data?
In order to reduce the user’s frustration, it’s very important to provide as much helpful information as possible in order to guide them in correcting their inputs. You should offer up-front suggestions so they know what’s expected, as well as clear error messages. If you want to dig into form validation UI requirements, here are some useful articles you should read:
An example that doesn’t use the constraint validation API
In order to illustrate this, the following is a simplified version of the previous example without the Constraint Validation API.
The HTML is almost the same; we just removed the HTML validation features.
Similarly, the CSS doesn’t need to change very much; we’ve just turned the :invalid CSS pseudo-class into a real class and avoided using the attribute selector that doesn’t work on Internet Explorer 6.
The big changes are in the JavaScript code, which needs to do much more heavy lifting.
The result looks like this:
As you can see, it’s not that hard to build a validation system on your own. The difficult part is to make it generic enough to use both cross-platform and on any form you might create. There are many libraries available to perform form validation, such as Validate.js.
Test your skills!
You’ve reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you’ve retained this information before you move on — see Test your skills: Form validation.
Summary
Client-side form validation sometimes requires JavaScript if you want to customize styling and error messages, but it always requires you to think carefully about the user. Always remember to help your users correct the data they provide. To that end, be sure to:
- Display explicit error messages.
- Be permissive about the input format.
- Point out exactly where the error occurs, especially on large forms.
Once you have checked that the form is filled out correctly, the form can be submitted. We’ll cover sending form data next.
Источник
От автора: в этой статье мы рассмотрим атрибут pattern и как с его помощью проводить валидацию форм, а именно html 5 проверка формы.
Валидация
Валидация форм, как и юзабилити, имеет жизненно важное значение для безопасности сайта. В процессе проверки перед отправкой формы оцениваются значения полей input на корректный формат ввода. К примеру, у нас есть поле input для ввода email’а, в таком случае значением должен выступать правильный адрес почты; адрес должен начинаться с цифры или буквы, затем знак @ и в конце доменное имя.
Спецификация HTML5 упростила процесс проверки формы, представив новые типы поля input: email, url и tel. Данные значения обеспечивают автоматическую валидацию. При любом несовпадении формата ввода данные input’ы будут выдавать ошибку, предотвращая отправку формы.
Однако ожидать полной обработки всех возможных сценариев с полем input непрактично. Скажем, у вас есть поля для имени пользователя, почтового индекса или другие специализированные типы данных, не входящих в спецификацию? Как проводить проверку этих полей? Вот тут нам и поможет атрибут pattern.
Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее
Применение атрибута pattern
Атрибут pattern применим только к полям input. С его помощью можно задавать наши собственные правила валидации значения поля input при помощи Регулярных Выражений (RegEx). И еще раз – если значение не совпадает с заданным шаблоном, то выскачет ошибка.
К примеру, у нас есть поле имени пользователя в форме. Стандартизированного типа для поля имени пользователя не существует, значит, мы воспользуемся обычным типом text:
<form action=«somefile.php»> <input type=«text» name=«username» placeholder=«Username»> </form> |
Зададим правило проверки при помощи атрибута pattern. В нашем примере значение поля должно состоять из букв нижнего регистра; никаких заглавных букв, цифр или других специальных символов. Кроме того, длина поля не должна превышать 15 символом. В форме RegEx данные правила можно записать в виде [a-z]{1,15}. Пропишите [a-z]{1,15} в качестве значения атрибута pattern для поля username.
<form action=«somefile.php»> <input type=«text» name=«username» placeholder=«Username» pattern=«[a-z]{1,15}»> </form> |
Теперь данное поле принимает только буквы нижнего регистра. Любое другое значение вызовет ошибку:
Как видно на скриншоте выше, в сообщении об ошибке сказано «Please match the requested format». Т.е. наша проверка формы работает, но это сообщение не дает представление пользователю о том, какой формат ввода от него требуется, а значит плохой UX.
Настройка сообщения о проверке
К нашему счастью мы можем настраивать текст сообщения, чтобы сделать его более информативным. В нашем распоряжении несколько способов. Самый простой это задать атрибут title для input’а:
<form action=«somefile.php»> <input type=«text» name=«username» placeholder=«Username» pattern=«[a-z]{1,15}» title=«Username should only contain lowercase letters. e.g. john»> </form> |
Теперь заголовок появляется с текстом сообщения по умолчанию:
И все же всплывающее сообщение неустойчиво. Если сравнить это сообщение с сообщением для поля email выше, то инструкция будет куда длиннее. Второй способ решает данную задачу.
Замена стандартного текста сообщения
Теперь давайте заменим стандартный текст «Please match the requested format» на наш. Нам понадобится немного JavaScript. Начнем с добавления id полю input для удобства выбора данного поля в JS.
<form action=«somefile.php»> <input type=«text» name=«username» placeholder=«Username» pattern=«[a-z]{1,15}» id=«username»> </form> |
Теперь мы можем выбрать наше поле через JS и присвоить ему переменную (код ниже или между тегов script, или в отдельном JS файле, или в панели JS на CodePen):
И в конце мы задаем текст сообщения, всплывающего при неправильном вводе.
input.oninvalid = function(event) { event.target.setCustomValidity(‘Username should only contain lowercase letters. e.g. john’); } |
Событие oninvalid наследуется от объекта event, в котором есть несколько свойств, среди которых target (элемент с неправильно введенным текстом) и validationMessage – содержит текст сообщения об ошибке. В примере выше мы переписали текст сообщения при помощи метода setCustomValidity(). Наше сообщение заменило стандартное.
Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее
Стили
Спецификация CSS3 добавила несколько удобных псевдоклассов в дополнение к новым типам поля input и методам, описанным выше, используемых для изменения стандартного сообщения об ошибке. И это псевдоклассы :valid and :invalid. С их помощью можно применять стили к элементам в зависимости от их состояния, к примеру:
input:invalid { border—color: red; } input, input:valid { border—color: #ccc; } |
Необходимо помнить несколько вещей при использовании псевдоклассов:
Первое, :valid применяется по умолчанию, даже если поле пустое. Т.е. в коде выше мы установили цвет по умолчанию border-color: #ccc;. Пустое значение всегда проходит проверку, если не добавить атрибут required. В таком случае значение поля становится неверным, и его рамка становится красной.
Стили для состояний valid и invalid применяются мгновенно с вводом пользователем текста, даже если значение пустое. Такое мгновенное изменение стилей может напугать пользователей.
Пару слов и стилизации всплывающих сообщений
Валидация форм стала новым стандартом спецификации HTML5, однако внешний вид всплывающих сообщений полностью лежит на разработчиках браузеров. В разных браузерах данные поля выглядят по-разному, и они могут не сочетаться с вашим UI.
Google Chrome убрал возможность настройки стилей всплывающего поля пару лет назад. Если же вам необходимо стилизовать поле под себя, то остается только полностью переписать данное поле с помощью JavaScript. Рассмотрим, как это сделать!
Расширяем функционал
Сейчас мы создадим полностью кастомное всплывающее поле, которое будет появляться, когда пользователь вводит неправильное значение. Для начала необходимо выбрать требуемые элементы с идентификаторами input и form:
var input = document.getElementById(‘username’); var form = document.getElementById(‘form’); |
Затем мы создаем новые элементы, которые будут хранить наше сообщение:
var elem = document.createElement(‘div’); elem.id = ‘notify’; elem.style.display = ‘none’; form.appendChild(elem); |
Мы создали новый DIV, присвоили ему id со значением notify и спрятали его при помощи display: none. В конце мы вставляем новый DIV в нашу форму.
Работаем с событиями
Нам необходимо обработать два события. Первое это invalid, которое вызывается при несовпадении значения с шаблоном. Код ниже для события invalid:
input.addEventListener(‘invalid’, function(event){ event.preventDefault(); if ( ! event.target.validity.valid ) { elem.textContent = ‘Username should only contain lowercase letters e.g. john’; elem.className = ‘error’; elem.style.display = ‘block’; input.className = ‘invalid animated shake’; } }); |
С помощью event.preventDefault(); мы блокируем всплывающее поле браузера. Взамен мы будем показывать наше поле DIV, внутрь которого мы добавили текст с классом error. Поле показывается при помощи изменения значения display: block;
Также input’у мы добавили класс invalid, в котором прописали красную рамку.
input.invalid { border—color: #DD2C00; } |
В дополнение можно добавить классы animated и shake из фреймворка Animate.css. Данные классы придадут аутентичности. Второе событие – input. Событие вызывается при изменении значения поля. Данное событие мы будем использовать для возврата поля в нормальное состояние, а также чтобы прятать всплывающее сообщение.
input.addEventListener(‘input’, function(event){ if ( ‘block’ === elem.style.display ) { input.className = »; elem.style.display = ‘none’; } }); |
В коде выше мы удаляем классы для поля input и прячем сообщение.
Теперь у нас полностью настроенное всплывающее сообщение. Попробуйте – введите любое значение:
Заключительные мысли
Стандартные типы поля input и атрибут pattern придадут вашей форме дополнительный уровень защиты, но не забывайте и про валидацию формы на стороне сервера. Как ни странно даже при отключенном JS последние версии браузеров показывают всплывающее сообщение и не отправляют форму. Safari не поддерживает атрибут pattern на момент написания статьи. Однако похожий функционал можно реализовать с помощью полифилла Webshim Lib. Надеюсь, вам понравился сегодняшний урок, и вы будете держать данную статью под рукой, когда вам понадобится воспользоваться HTML5 валидацией формы.
Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее
Верстка. Быстрый старт
Практический курс по верстке адаптивного сайта с нуля!
Смотреть
Валидация форм
Последнее обновление: 08.04.2016
Итак, в нашем распоряжении имеются различные элементы, которые мы можем использовать на форме. Мы можем вводить в них различные значения. Однако нередко
пользователи вводят не совсем корректные значения: например, ожидается ввод чисел, а пользователь вводит буквы и т.д. И для предупреждения и проверки некорректного
ввода в HTML5 существует механизм валидации.
Преимущество использования валидации в HTML5 заключается в том, что пользователь после некорректного ввода может сразу получить сообщение об ошибке и внести
соответствующие изменения в введенные данные.
Для создания валидации у элементов форм HTML5 используется ряд атрибутов:
-
required: требует обязательного ввода значения. Для элементов textarea, select, input (с типом text, password, checkbox, radio,
file, datetime-local, date, month, time, week, number, email, url, search, tel) -
min и max: минимально и максимально допустимые значения. Для элемента input с типом datetime-local,
date, month, time, week, number, range -
pattern: задает шаблон, которому должны соответствовать вводимые данные. Для элемента input с типом text, password, email, url, search, tel
Атрибут required
Атрибут required требует обязательного наличия значения:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Валидация в HTML5</title> </head> <body> <form method="get"> <p> <label for="login">Логин:</label> <input type="text" required id="login" name="login" /> </p> <p> <label for="password">Пароль:</label> <input type="password" required id="password" name="password" /> </p> <p> <input type="submit" value="Отправить" /> </p> </form> </body> </html>
Если мы не введем в эти поля никаких данных, оставив их пустыми, и нажмем на кнопку отправки, то браузер высветит нам сообщения об ошибке, а данные не будут отправлены на сервер:
В зависимости от браузера визуализация сообщения может несколько отличаться. Также границы некорректного поля ввода могут окрашиваться в красный цвет. Например, поведение при отправке
пустых сообщений в Firefox:
Атрибуты max и min
Для ограничения диапазона вводимых значений применяются атрибуты max и min:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Валидация в HTML5</title> </head> <body> <form method="get"> <p> <label for="age">Возраст:</label> <input type="number" min="1" max="100" value="18" id="age" name="age"/> </p> <p> <input type="submit" value="Отправить" /> </p> </form> </body> </html>
Атрибут pattern
Атрибут pattern задает шаблон, которому должны соответствовать данные. Для определения шаблона используется язык так называемых
регулярных выражений. Рассмотрим самые простейшие примеры:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Валидация в HTML5</title> </head> <body> <form method="get"> <p> <label for="phone">Телефон:</label> <input type="text" placeholder="+1-234-567-8901" pattern="+d-d{3}-d{3}-d{4}" id="phone" name="phone" /> </p> <p> <input type="submit" value="Отправить" /> </p> </form> </body> </html>
Здесь для ввода номера телефона используется регулярное выражение +d-d{3}-d{3}-d{4}
. Оно означает, что первым элементом в номере
должен идти знак плюс +. Выражение d представляет любую цифру от 0 до 9. Выражение d{3}
означает три подряд идущих цифры, а
d{4}
— четыре цифры подряд. То есть это выражение будет соответствовать номеру телефона в формате «+1-234-567-8901».
Если мы введем данные, которые не соответствуют этому шаблону, и нажмем на отправку, то браузер отобразит ошибку:
Отключение валидации
Не всегда валидация является желаемой, иногда требуется ее отключить. И в этом случае мы можем использовать либо у элемента формы атрибут novalidate,
либо у кнопки отправки атрибут formnovalidate:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Валидация в HTML5</title> </head> <body> <form novalidate method="get"> <p> <label for="phone">Телефон:</label> <input type="text" placeholder="+1-234-567-8901" pattern="+d-d{3}-d{3}-d{4}" id="phone" name="phone" /> </p> <p> <input type="submit" value="Отправить" formnovalidate /> </p> </form> </body> </html>
При создании веб-приложений важно серьезно относиться к безопасности, особенно, когда приходится иметь дело с получением данных от пользователей.
Общее правило безопасности — не доверять никому, так что нельзя надеяться на то, что пользователи всегда будут вводить в формы правильные значения. Например, вместо ввода в поле правильного email-адреса, пользователь может ввести неверный адрес, или вообще какие-нибудь вредоносные данные.
Когда дело доходит до валидации пользовательских данных, ее можно проводить как на стороне клиента (в веб-браузере), так и на серверной стороне.
Ранее валидацию на стороне клиента можно было провести только с помощью JavaScript. Но все изменилось (или почти изменилось), так как с помощью HTML5 валидацию можно проводить средствами браузера, без необходимости писать сложные скрипты для валидации на JavaScript.
Валидация форм с помощью HTML5
HTML5 предоставляет довольно надежный механизм, основанный на следующих атрибутах тега <input />
: type
, pattern
и require
. Благодаря этим новым атрибутам вы можете переложить некоторые функции проверки данных на плечи браузера.
Давайте рассмотрим эти атрибуты, чтобы понять, как они могут помочь в валидации форм.
Атрибут type
Этот атрибут говорит, какое поле ввода отобразить для обработки данных, например, уже знакомое поле типа <input type="text" />
Некоторые поля ввода уже предоставляют стандартные способы валидации, без необходимости писать дополнительный код. Например, <input type="email" />
проверяет поле на то, что введенное значение соответствует шаблону правильного email адреса. Если в поле введен неверный символ, форму нельзя будет отправить, пока значение не будет исправлено.
Попробуйте поиграться со значениями поля email в нижеприведенной демонстрации.
Также существуют другие стандартные типы полей, вроде <input type="number" />
, <input type="url" />
и <input type="tel" />
для валидации чисел, URL’ов и телефонных номеров соотвествено.
Замечание: формат телефонного номера различается для разных стран из-за несоответствия количества цифр в телефонных номерах и разности форматов. Как результат, спецификация не определяет алгоритм проверки телефонных номеров, так что на время написания статьи данная возможность слабо поддерживается браузерами.
К счастью для нас, валидацию телефонных номеров можно провести с использованием атрибута pattern
, который принимает как аргумент регулярное выражение, который мы рассмотрим далее.
Атрибут pattern
Атрибут pattern
, скорее всего, заставит многих фронтенд-разработчиков прыгать от радости. Этот атрибут принимает регулярное выражение (аналогичное формату регулярных выражений JavaScript), по которому будет проверяться корректность введенных в поле данных.
Регулярные выражения это язык, использующийся для разбора и манипуляции текстом. Они часто используются для сложных операций поиска и замены, а также для проверки корректности введенных данных.
На сегодняшний день регулярные выражения включены в большинство популярных языков программирования, а также во многие скриптовые языки, редакторы, приложения, базы данных, и утилиты командной строки.
Регулярные выражения (RegEX) являются мощным, кратким и гибким инструментом для сопоставления строки текста, вроде отдельных символов, слов или шаблонов символов.
Передав регулярное выражение в качестве значения атрибута pattern
можно указать, какие значения приемлемы для данного поля ввода, а также проинформировав пользователя об ошибках.
Давайте посмотрим на пару примеров использования регулярных выражений для валидации значения полей ввода.
Телефонные номера
Как упоминалось ранее, тип поля tel
не полностью поддерживается браузерами из-за несоответствия форматов номеров телефонов в разных странах.
Например, в некоторых странах формат телефонных номеров представляется в виде xxxx-xxx-xxxx
, и сам телефонный номер будет что-то вроде этого: 0803-555-8205.
Регулярное выражение, которому соответствует данный шаблон, такое: ^d{4}-d{3}-d{4}$
. В коде это можно записатьтак:
<label for="phonenum">Phone Number:</label> <input type="tel" pattern="^d{4}-d{3}-d{4}$" >
Буквенно-цифровые значения
Следующий шаблон соответствует набору буквенно-цифровых значений (комбинации букв английского алфавита и цифр):
<input type="text" pattern="[a-zA-Z0-9]+" >
Имя пользователя в Twitter
Данное регулярное выражение соответствует имени пользователя в твиттере, с предваряющим символом @, например@tech4sky
:
<input type="text" pattern="^@[A-Za-z0-9_]{1,15}$" >
Цвет в шестнадцатеричном виде
Эта регулярка соответствует цвету в шестнадцатеричном виде, например #3b5998 или #000:
<input type="text" pattern="^#+([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$" >
Подсказки
Для того, чтобы дать пользователю подсказку о шаблоне, или сообщить об ошибке в случае неверно введенного в поле значения, можно использовать атрибут title:
<input type="text" name="ssn" pattern="^d{3}-d{2}-d{4}$" title="Номер Социального Страхования" />
Если вы еще не знакомы с регулярными выражениями, вы можете ознакомиться с этим документом. В большинстве случаев вы всегда можете воспользоваться гуглом для поиска нужных вам регулярных выражений, или же использоватьвспомогательные инструменты.
Атрибут required
Это атрибут булевого типа, использующийся для указания того, что значение данного поле обязательно заполнить для того, чтобы отправить форму. При добавлении этого атрибута полю браузер потребует от пользователя заполнить данное поле перед отправкой формы.
Это избавляет нас от реализации проверки полей с помощью JavaScript, что может сохранить немного времени разработчикам.
Например: <input type="text" name="my_name" required />
или <input type="text" name="my_name" required="required" />
(для совместимости с XHTML)
Во всех демках, которые вы видели выше, используют атрибут required
, так что вы можете попробовать его в действии, попытавшись отослать форму без заполнения полей.
Заключение
Поддержка валидации форм браузерами довольно хороша, а для старых браузеров вы можете использовать полифиллы.
Стоит отметить, что надеяться на валидацию только на стороне браузера опасно, так как эти проверки могут быть легко обойдены злоумышленниками или ботами.
Не все браузеры поддерживают HTML5, и не все данные, посланные вашему скрипту, придут с вашей формы. Это значит, что перед тем, как окончательно принять данные от пользователя, необходимо проверить их корректность на стороне сервера.