В этой статье мы рассмотрим поля форм HTML и возможности валидации, предлагаемые HTML5. Также мы рассмотрим, как эти возможности можно улучшить с помощью CSS и JavaScript.
Что такое Контролируемая Валидация?
У каждого поля формы есть своё назначение. И это назначение часто регулируется ограничениями — или правилами, определяющими, что и что не должно вводиться в каждое поле формы. Например, поле email
потребует валидный адрес электронной почты; поле password
может требовать определенные типы символов и иметь минимальное количество требуемых символов; а текстовое поле может иметь ограничение на количество вводимых символов.
Современные браузеры имеют возможность проверять, соблюдаются ли эти ограничения со стороны пользователей, и могут предупреждать их, когда эти правила нарушены. Это называется контролируемой валидацией.
Клиентская сторона против Серверной стороны Валидации
Бóльшая часть JavaScript-кода, написанного в ранних годах языка, занималась клиентской стороной валидации форм. Даже сегодня разработчики тратят значительное время на написание функций для проверки значений полей. Необходимо ли это ещё в современных браузерах? Скорее всего, нет. В большинстве случаев, это действительно зависит от того, что вы пытаетесь сделать.
Но сначала, вот большое предупреждение:
Клиентская валидация — это удобство, которое может предотвратить общие ошибки ввода данных до того, как приложение потратит время и пропускную способность, отправляя данные на сервер. Это не замена серверной валидации!
Всегда очищайте данные на сервере. Не каждый запрос будет приходить из браузера. Даже если это так, гарантий того, что браузер проверил данные, нет. Любой, кто знает, как открыть инструменты разработчика браузера, также может обойти ваш тщательно созданный HTML и JavaScript.
Поля ввода HTML5
HTML предлагает:
<textarea>
для многострочных текстовых полей<select>
для выпадающего списка опций<button>
для … кнопок
Но вы будете использовать <input>
чаще всего:
<input type="text" name="username" />
Атрибут type
устанавливает тип управления, и есть большой выбор вариантов:
type |
description |
---|---|
button |
a button with no default behavior |
checkbox |
a check/tick box |
color |
a color picker |
date |
a date picker for the year, month, and day |
datetime-local |
a date and time picker |
email |
an email entry field |
file |
a file picker |
hidden |
a hidden field |
image |
a button which displays the image defined by the src attribute |
month |
a month and year picker |
number |
a number entry field |
password |
a password entry field with obscured text |
radio |
a radio button |
range |
a slider control |
reset |
a button that resets all form inputs to their default values (but avoid using this, as it’s rarely useful) |
search |
a search entry field |
submit |
a form submission button |
tel |
a telephone number entry field |
text |
a text entry field |
time |
a time picker with no time zone |
url |
a URL entry field |
week |
a week number and year picker |
Браузер возвращается к text
, если вы пропустите атрибут type
или он не поддерживает вариант. Современные браузеры хорошо поддерживают все типы, но старые браузеры все равно покажут текстовое поле ввода.
Другие полезные атрибуты <input>
включают:
attribute | description |
---|---|
accept |
file upload type |
alt |
alternative text for the image types |
autocomplete |
hint for field auto-completion |
autofocus |
focus field on page load |
capture |
media capture input method |
checked |
checkbox/radio is checked |
disabled |
disable the control (it won’t be validated or have its value submitted) |
form |
associate with a form using this ID |
formaction |
URL for submission on submit and image buttons |
inputmode |
data type hint |
list |
ID of <datalist> autocomplete options |
max |
maximum value |
maxlength |
maximum string length |
min |
minimum value |
minlength |
minimum string length |
name |
name of control, as submitted to server |
pattern |
a regular expression pattern, such as [A-Z]+ for one or more uppercase characters |
placeholder |
placeholder text when the field value is empty |
readonly |
the field is not editable, but it will still be validated and submitted |
required |
the field is required |
size |
the size of the control (often overridden in CSS) |
spellcheck |
set true or false spell-checking |
src |
image URL |
step |
incremental values in numbers and ranges |
type |
field type (see above) |
value |
the initial value |
Поля вывода HTML
Помимо входных типов, HTML5 предоставляет только для чтения выходные данные:
output
: текстовый результат вычисления или действия пользователяprogress
: индикатор прогресса с атрибутамиvalue
иmax
meter
: шкала, которая может изменяться между зеленым, желтым и красным в зависимости от значений, установленных для атрибутовvalue
,min
,max
,low
,high
иoptimum
.
Метки ввода
Поля должны иметь связанный <label>
, который можно обернуть вокруг элемента:
<label>your name <input type="text" name="name" /><label>
Или связать поле с меткой с помощью атрибута for
:
<label for="nameid">your name</label>
<input type="text" id="nameid" name="name" />
Метки важны для доступности. Возможно, вы сталкивались с формами, которые используют placeholder
для экономии места на экране:
<input type="text" name="name" value="" placeholder="your name" />
Текст заполнителя исчезает, как только пользователь что-то вводит — даже один пробел. Лучше показывать метку, чем заставлять пользователя запоминать, что требуется от поля!
Поведение ввода
Типы полей и атрибуты ограничений изменяют поведение ввода в браузере. Например, для ввода number
на мобильных устройствах отображается цифровой клавиатура. Поле может показывать счетчик, и нажатия клавиш вверх/вниз на клавиатуре будут увеличивать и уменьшать значения.
Большинство типов полей очевидны, но есть исключения. Например, кредитные карты являются числовыми, но увеличение/уменьшение счетчика бесполезно, и слишком легко нажимать вверх или вниз при вводе 16-значного числа. Лучше использовать стандартный тип text
, но установить атрибут inputmode
в numeric
, что показывает соответствующую клавиатуру. Установка autocomplete="cc-number"
также предлагает любые предварительно настроенные или ранее введенные номера карт.
Использование правильного поля type
и autocorrect
предлагает преимущества, которые было бы трудно достичь на JavaScript. Например, некоторые мобильные браузеры могут:
- импортировать данные кредитной карты, используя камеру для сканирования карты
- импортировать одноразовые коды, отправленные по SMS
Автоматическая проверка
Браузер обеспечивает соответствие введенного значения ограничениям, определенным атрибутами type
, min
, max
, step
, minlength
, maxlength
, pattern
и required
. Например:
<input type="number" min="1" max="100" required />
Попытка отправки пустого значения предотвращает отправку формы и показывает следующее сообщение в Chrome:
Сплетники не разрешат значения вне диапазона от 1 до 100. Похожие сообщения о валидации появляются, если вы введете строку, которая не является числом. Все без единой строки JavaScript.
Вы можете отключить валидацию браузера следующим образом:
- добавив атрибут
novalidate
к элементу<form>
- добавив атрибут
formnovalidate
к кнопке или изображению отправки
Создание пользовательских JavaScript-входов
Если вы пишете новый компонент ввода даты на основе JavaScript, пожалуйста, остановитесь и отойдите от клавиатуры!
Написание пользовательских элементов управления вводами – это сложно. Вам нужно учитывать мышь, клавиатуру, тач, речь, доступность, размеры экрана и что произойдет, если JavaScript не сработает. Вы также создаете другую пользовательскую интерфейс. Может быть, ваш элемент управления превосходит стандартный выбор даты на настольных компьютерах, iOS и Android, но непонятный интерфейс сбивать с толку некоторых пользователей.
Есть три основные причины, по которым разработчики выбирают создание входов на основе JavaScript.
1. Стандартные элементы управления сложно стилизовать
Стилизация CSS ограничена и часто требует хаков, таких как наложение входа на псевдоэлементы ::before
и ::after
метки. Ситуация улучшается, но задайте вопрос любому дизайну, который ставит форму превыше функции.
2. Современные типы <input>
не поддерживаются в старых браузерах
По сути, вы программируете под Internet Explorer. Пользователи IE не получат выбор даты, но могут вводить даты в формате ГГГГ-ММ-ДД
. Если ваш клиент настаивает, то загрузите полифилл только в IE. Современным браузерам это не нужно.
3. Вам требуется новый тип ввода, который никогда не был реализован ранее
Такие ситуации редки, но всегда начинайте с подходящих полей HTML5. Они быстрые и работают даже до загрузки скрипта. Вы можете постепенно улучшать поля по мере необходимости. Например, немного JavaScript может обеспечить, чтобы конечная дата мероприятия календаря наступала после начальной даты.
В заключение: избегайте изобретения собственных HTML-элементов управления!
Стилизация валидации CSS
Вы можете применять следующие псевдо-классы к полям ввода для стилизации их в зависимости от текущего состояния:
selector | description |
---|---|
:focus |
the field with focus |
:focus-within |
an element contains a field with focus (yes, it’s a parent selector!) |
:focus-visible |
an element has focus owing to keyboard navigation, so a focus ring or more evident styling is necessary |
:required |
a field with a required attribute |
:optional |
a field without a required attribute |
:valid |
a field that has passed validation |
:invalid |
a field that has not passed validation |
:user-valid |
a field that has passed validation after the user has interacted with it (Firefox only) |
:user-invalid |
a field that hasn’t passed validation after the user has interacted with it (Firefox only) |
:in-range |
the value is within range on a number or range input |
:out-of-range |
the value is out of range on a number or range input |
:disabled |
a field with a disabled attribute |
:enabled |
a field without a disabled attribute |
:read-only |
a field with a read-only attribute |
:read-write: |
a field without a read-only attribute |
:checked |
a checked checkbox or radio button |
:indeterminate |
an indeterminate checkbox or radio state, such as when all radio buttons are unchecked |
:default |
the default submit button or image |
Вы можете стилизовать текстовое содержимое placeholder
с помощью псевдо-элемента ::placeholder
:
/* синий плейсхолдер для полей электронной почты */
input[type="email"]::placeholder {
color: blue;
}
Вышеупомянутые селекторы имеют одинаковую специфичность, поэтому порядок может быть важен. Рассмотрим пример:
input:invalid { color: red; }
input:enabled { color: black; }
Неверные входные данные имеют красный текст, но он применяется только к полям с атрибутом disabled
— так что все активные поля имеют черный цвет.
Браузер применяет стили валидации при загрузке страницы. Например, в следующем коде каждое неверное поле получает красную границу:
:invalid {
border-color: #900;
}
Пользователю предстоит столкнуться с пугающим рядом красных квадратов перед тем, как он начнет взаимодействовать с формой. Показать ошибки валидации после первого отправления или при изменении значения обеспечит лучший опыт. Вот здесь-то и вступает в игру JavaScript…
JavaScript и API валидации ограничений
API валидации ограничений предоставляет возможности настройки формы, которые могут улучшить стандартную проверку полей HTML. Вы можете:
- приостановить валидацию до тех пор, пока пользователь не взаимодействует с полем или не отправляет форму
- показать сообщения об ошибках с настраиваемым стилем
- предоставить настраиваемую валидацию, которая невозможна только с помощью HTML. Это часто необходимо, когда нужно сравнить два входа – например, когда вы вводите адрес электронной почты или телефонный номер, проверяете, что “новый” и “подтверждающий” пароли имеют одинаковое значение, или убеждаетесь, что одна дата наступает после другой.
Проверка формы
Перед использованием API ваш код должен отключить стандартную валидацию и сообщения об ошибках, установив свойство формы noValidate
в true
(что аналогично добавлению атрибута novalidate
):
const myform = document.getElementById('myform');
myform.noValidate = true;
Затем вы можете добавить обработчики событий – например, когда форма отправляется:
myform.addEventListener('submit', validateForm);
Обработчик может проверить, действительна ли вся форма, используя методы checkValidity()
или reportValidity()
, которые возвращают true
, если все входы формы действительны. (Разница в том, что checkValidity()
проверяет, подвергаются ли какие-либо входы ограничению валидации.)
Документация Mozilla объясняет:
Событие
invalid
также срабатывает на каждом невалидном поле. Оно не всплывает: обработчики должны быть добавлены к каждому контролю, который его использует.
// проверять форму при отправке
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// форма валидна - проводить дополнительные проверки
}
else {
// форма невалидна - отменить отправку
e.preventDefault();
}
};
A valid form could now incur further validation checks. Similarly, an invalid form could have invalid fields highlighted.
Проверка полей
Отдельные поля имеют следующие свойства проверки ограничений:
-
willValidate
: возвращаетtrue
если элемент является кандидатом для проверки ограничений. -
validationMessage
: сообщение о проверке. Это будет пустая строка, если поле валидно. -
valitity
: объект ValidityState. У него есть свойствоvalid
, которое устанавливается вtrue
, если поле является действительным. Если оно равноfalse
, одно или несколько из следующих свойств будут равныtrue
:ValidityState описание .badInput
браузер не может понять ввод .customError
было установлено сообщение о настройке действительности .patternMismatch
значение не соответствует указанному атрибуту pattern
.rangeOverflow
значение больше, чем атрибут max
.rangeUnderflow
значение меньше, чем атрибут min
.stepMismatch
значение не соответствует правилам атрибута step
.tooLong
длина строки больше, чем атрибут maxlength
.tooShort
длина строки меньше, чем атрибут minlength
.typeMismatch
значение не является действительным email или URL .valueMissing
требуемое значение пустое
Отдельные поля имеют следующие методы проверки валидации ограничений:
setCustomValidity(message)
: устанавливает сообщение об ошибке для недействительного поля. Пустая строка должна быть передана, когда поле действительно, иначе поле останется недействительным навсегда.checkValidity()
: возвращаетtrue
, если ввод действителен. Свойствоvalitity.valid
делает то же самое, ноcheckValidity()
также вызывает событиеinvalid
на поле, что может быть полезно.
Обработчик функции validateForm()
может перебирать каждое поле и применять класс invalid
к его родительскому элементу при необходимости:
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// форма действительна - проверяем дальше
}
else {
// форма недействительна - отменяем отправку
e.preventDefault();
// применяем класс invalid
Array.from(form.elements).forEach(i => {
if (i.checkValidity()) {
// поле действительно - удаляем класс
i.parentElement.classList.remove('invalid');
}
else {
// поле недействительно - добавляем класс
i.parentElement.classList.add('invalid');
}
});
}
};
Предположим, что ваш HTML определил поле электронной почты:
<div>
<label for="email">email</label>
<input type="email" id="email" name="email" required />
<p class="help">Please enter a valid email address</p>
</div>
Скрипт применяет класс invalid
к <div>
когда email не указан или недействителен. CSS может показывать или скрывать сообщение о валидации при отправке формы:
.help { display: none; }
.invalid .help { display: block; }
.invalid label, .invalid input, .invalid .help {
color: red;
border-color: red;
}
Создание пользовательского валидатора формы
Следующий демонстрационный пример показывает пример контактной формы, которая требует имя пользователя и либо адрес электронной почты, либо номер телефона, либо оба:
Он реализован с использованием общего класса валидации формы под названием FormValidate
. При создании объекта передается элемент формы. Возможен второй параметр:
true
для валидации каждого поля при взаимодействии пользователя с нимfalse
(по умолчанию) для валидации всех полей после первой отправки (валидация на уровне поля происходит после этого)
// валидация контактной формы
const contactForm = new FormValidate(document.getElementById('contact'), false);
Метод .addCustom(field, func)
определяет пользовательские функции валидации. Следующий код обеспечивает, что либо поле email
, либо поле tel
являются действительными (ни одно из них не имеет атрибута required
):
// пользовательская валидация - email и/или телефон
const
email = document.getElementById('email'),
tel = document.getElementById('tel');
contactForm.addCustom(email, f => f.value || tel.value);
contactForm.addCustom(tel, f => f.value || email.value);
A FormValidate
object monitors both of the following:
focusout
события, которые затем проверяют отдельное поле- события
submit
формы, которые затем проверяют каждое поле
Оба вызывают метод .validateField(field)
, который проверяет, проходит ли поле стандартную валидацию ограничений. Когда это так, любые назначенные пользовательские функции валидации для этого поля выполняются последовательно. Все они должны возвращать true
для того, чтобы поле считалось действительным.
Неверные поля имеют примененный класс invalid
к родительскому элементу поля, который отображает сообщение справки красного цвета с помощью CSS.
Наконец, объект вызывает пользовательскую функцию submit
при валидности всей формы:
// пользовательский submit
contactForm.submit = e => {
e.preventDefault();
alert('Form is valid!\n(open the console)');
const fd = new FormData(e.target);
for (const [name, value] of fd.entries()) {
console.log(name + ': ' + value);
}
}
В качестве альтернативы можно использовать стандартный addEventListener
для обработки событий submit
формы, так как FormValidate
предотвращает запуск дополнительных обработчиков при невалидной форме.
Усовершенствование форм
Формы являются основой всех веб-приложений, и разработчики тратят значительное время на манипуляции с пользовательским вводом. Ограничительная валидация хорошо поддерживается: браузеры могут обрабатывать большинство проверок и показывать соответствующие варианты ввода.
Рекомендации:
- Используйте стандартные типы HTML-входов, где это возможно. Установите атрибуты
min
,max
,step
,minlength
,maxlength
,pattern
,required
,inputmode
, иautocomplete
по мере необходимости. - При необходимости используйте немного JavaScript для активации пользовательской валидации и сообщений.
- Для более сложных полей постепенно улучшайте стандартные входы.
Наконец: забудьте о Internet Explorer!
Если ваши клиенты в основном не используют Internet Explorer, нет необходимости реализовывать свои собственные функции проверки валидации. Все поля ввода HTML5 работают в IE, но могут потребовать больше усилий от пользователя. (Например, IE не обнаружит, когда вы вводите неверный адрес электронной почты.) Вы все равно должны проверять данные на сервере, поэтому рассмотрите возможность использования этого в качестве основы для проверки ошибок в IE.
Часто задаваемые вопросы (FAQ) о HTML-формах и ограничительной валидации
Почему важна валидация HTML-форм?
Валидация HTML-форм является важным аспектом веб-разработки. Она обеспечивает, что данные, введенные пользователями в форму, соответствуют определенным критериям перед отправкой на сервер. Это не только поддерживает целостность данных, но и улучшает пользовательский опыт, предоставляя мгновенную обратную связь о правильности введенных данных. Без валидации форм существует риск получения неправильных, неполных или даже вредоносных данных, что может привести к различным проблемам, включая порчу данных, нарушение безопасности и аварии системы.
Как HTML5 улучшает валидацию форм?
HTML5 вводит несколько новых элементов и атрибутов форм, которые значительно упрощают и делают более эффективной валидацию форм. Например, он предоставляет новые типы ввода, такие как email, URL и number, которые автоматически валидируют введенные данные в зависимости от типа. HTML5 также вводит новые атрибуты, такие как required, pattern и min/max, которые позволяют указывать различные ограничения на вводимые данные. Более того, HTML5 предоставляет встроенный API валидации, который позволяет выполнять пользовательскую валидацию с помощью JavaScript.
Могу ли я выполнять валидацию форм без JavaScript?
Да, вы можете выполнять базовую валидацию формы с использованием только HTML5. HTML5 предоставляет несколько новых типов ввода и атрибутов, которые позволяют указывать различные ограничения на вводимые данные. Например, вы можете использовать атрибут required, чтобы сделать поле обязательным, атрибут pattern для обеспечения определенного формата и атрибуты min/max для установки диапазона для числовых входов. Однако для более сложной валидации вам все равно может потребоваться использовать JavaScript.
Как я могу настроить сообщения об ошибках валидации формы HTML5?
HTML5 предоставляет API валидации, который позволяет настроить сообщения об ошибках. Вы можете использовать метод setCustomValidity объекта ValidityState для установки пользовательского сообщения об ошибке для поля. Этот метод принимает строковый аргумент, который становится сообщением о валидации поля, когда поле недействительно. Вы можете вызывать этот метод в ответ на событие invalid, которое срабатывает, когда поле не проходит валидацию.
Как отключить валидацию формы HTML5?
Вы можете отключить валидацию формы HTML5, добавив атрибут novalidate к элементу формы. Когда этот атрибут присутствует, браузер не будет выполнять никакой валидации формы при ее отправке. Это может быть полезно, если вы хотите полностью обрабатывать валидацию на стороне сервера или с использованием пользовательского JavaScript.
Как в HTML5 проверить несколько полей вместе?
HTML5 не предоставляет встроенного способа проверки нескольких полей вместе. Однако это можно реализовать с помощью JavaScript. Вы можете написать пользовательскую функцию проверки, которая проверяет значения нескольких полей и устанавливает пользовательское сообщение о достоверности, если они не соответствуют требуемым критериям. Вы можете вызвать эту функцию в ответ на событие отправки формы или события ввода/изменения полей.
Как я могу проверить поле на основе значения другого поля в HTML5?
HTML5 не предоставляет встроенного способа проверки поля на основе значения другого поля. Однако это можно реализовать с помощью JavaScript. Вы можете написать пользовательскую функцию проверки, которая проверяет значение одного поля по отношению к значению другого поля и устанавливает пользовательское сообщение о достоверности, если они не совпадают. Вы можете вызвать эту функцию в ответ на события ввода/изменения полей.
Как я могу выполнить асинхронную проверку в HTML5?
HTML5 не поддерживает асинхронную проверку из коробки. Однако это можно реализовать с помощью JavaScript. Вы можете написать пользовательскую функцию проверки, которая выполняет асинхронную операцию, такую как AJAX-запрос, и устанавливает пользовательское сообщение о достоверности на основе результата. Вы можете вызвать эту функцию в ответ на события ввода/изменения полей или на событие отправки формы.
Как я могу стилизовать сообщения об ошибках в HTML5 форм проверки?
Внешний вид сообщений об ошибках валидации HTML5 форм определяется браузером и не может быть напрямую стилизован с использованием CSS. Однако вы можете создавать пользовательские сообщения об ошибках с помощью JavaScript и стилизовать их по своему усмотрению. Вы можете использовать API валидации для определения, когда поле недействительно, и отображать соответствующее пользовательское сообщение об ошибке.
Как проверить валидацию HTML-формы?
Вы можете проверить валидацию HTML-формы, вводя различные типы данных в поля и пытаясь отправить форму. Вам следует тестировать как с действительными, так и с недействительными данными, чтобы обеспечить корректную работу валидации во всех случаях. Вы также можете использовать автоматизированные инструменты тестирования или библиотеки для проведения более всестороннего тестирования.
Source:
https://www.sitepoint.com/html-forms-constraint-validation-complete-guide/