JavaScript: Проверка формы с Constraint Validation API
Проверка на стороне клиента не заменяет проверку на стороне сервера!
Всегда проверяйте входящие пользовательские данные на сервере. Не каждый запрос будет исходить от браузера, и не каждый браузер будет запускать код проверки. Проверка на стороне клиента — это усовершенствование, которое делает вашу систему более удобной в использовании.
Тем не менее вам может не потребоваться JavaScript для более простой проверки формы…
Проверка поля HTML5
Современные браузеры, поддерживающие HTML5, могут проверять поля без JavaScript. Атрибут type
устанавливает ограничения и может изменять пользовательский интерфейс стандартного поля <input>
:
Тип | Описание |
---|---|
button | кнопка без поведения по умолчанию |
checkbox | флажок или переключатель |
color | выбор цвета |
date | выбор даты для года, месяца и дня |
datetime-local | выбор даты и времени |
email | ввод email |
file | выбор файла |
hidden | скрытое поле |
image | кнопка, которая отображает изображение заданное в src атрибуте |
month | выбор месяца и года |
number | ввод номера |
password | ввод пароля (скрытый текст) |
radio | радио кнопка |
range | ползунок |
reset | сбрасывает все поля формы до значений по умолчанию |
search | поле поиска |
submit | кнопка отправки формы |
tel | телефонный номер |
text | текстовый ввод |
time | выбор времени (без временной зоны) |
url | ввод URL |
week | выбор номера недели и года |
Если вы не указываете или используете неподдерживаемый атрибут, браузер назначает полю тип text
. Это должно позволить пользователю вводит данные в старых браузерах, даже если это не может быть проверено автоматически.
Другие атрибуты управления ограничениями включают:
Атрибут | Описание |
---|---|
accept | тип загружаемого файла |
alt | атрибут alt для изображения |
autocomplete | подсказка автодополнения |
autofocus | поле фокуса |
capture | метод захвата мультимедиа |
checked | отмеченный checkbox или radio |
disabled | отключённое поле — оно не проверяется и не отправляется |
form | связать с формой, используя указанный id |
formaction | URL для отправки (submit и button ) |
inputmode | подсказка типа данных (none , text , tel , url , email , numeric , decimal , search ) |
list | id <datalist> |
max | максимальное значение |
maxlength | максимальная длинна строки |
min | минимальное значение |
minlength | минимальная длинна строки |
name | имя элемента управления (отправляется на сервер) |
pattern | регулярное выражение шаблона проверки поля, напр. [1-3]+ одна и больше цифр от 1 до 3 |
placeholder | текст-заполнитель для пустого поля |
readonly | Поле не может редактироваться - оно проверяется и отправляется |
required | обязательное поле |
size | размер элемента управления, обычно переопределяется в CSS |
spellcheck | устанавливается true или false для проверки орфографии |
src | URL изображения |
step | шаг увеличения значения в number и/или range |
value | начальное значение |
Интерфейс input
Типы полей и атрибуты ограничений могут изменить поведение пользовательского интерфейса браузера. Ввод числа показывает цифровую клавиатуру на мобильных устройствах, а также может отображать счётчик и разрешать нажатия клавиш вверх/вниз для увеличения и уменьшения значений.
Используйте самый очевидный тип type
, но будьте осторожны с особыми случаями, такими как кредитные карты. Это числовые значения, но ролик мыши и курсорные клавиши бесполезны. Лучше использовать стандартный ввод text
:
<input
type="text"
name="ccnumber"
inputmode="numeric"
autocomplete="cc-number"
/>
Браузер может предлагать такие функции, как съёмка камерой или подтверждение по SMS, когда встречает тип autocomplete
.
Встроенная проверка/валидация
Браузер гарантирует, что значение соответствует ограничениям атрибутов type
, min
, max
, step
, minlength
, maxlength
, pattern
, и required
:
<input type="number" min="1" max="100" required />
Попытка отправить пустое, недопустимое или выходящее за пределы диапазона, останавливает отправку формы и показывает общее сообщение об ошибке. Вы можете остановить проверку браузер по умолчанию, добавив:
- атрибут
novalidate
в<form>
, или - атрибут
formnovalidate
в кнопку отправки формы
CSS стили проверки/валидации
Следующие псевдоклассы позволяют стилизовать input
в соответствии с его состоянием:
Селектор | Описание |
---|---|
:focus | Поле на котором фокус |
:focus-within | элемент содержащий полое с фокусом |
:focus-visible | элемент на который переведён фокус с помощью клавиатуры |
:required | поле с атрибутом required |
:optional | поле без атрибута required |
:valid | поле прошедшее проверку |
:invalid | поле не прошедшее валидацию |
:user-valid | поле прошедшее валидацию после взаимодействия с пользователем (только Firefox) |
:user-invalid | поле не прошедшее валидацию после взаимодействия с пользователем (только Firefox) |
:in-range | значение находится в пределах допустимого диапазона |
:out-of-range | значение выходит за пределы допустимого диапазона |
:disabled | поле с атрибутом disabled |
:enabled | поле без атрибута disabled |
:read-only | поле с атрибутом read-only |
:read-write | поле без атрибута read-only |
:checked | отмеченный checkbox или radio button |
:indeterminate | неопределённое состояние checkbox или radio button |
:default | элементы установленные по умолчанию |
Эти селекторы имеют одинаковую специфичность, поэтому порядок не важен. Например:
input:invalid { color: red; }
input:enabled { color: blue; }
Поля input
с недопустимыми значениями окрашиваются в красный, но это переопределяется, потому что все не отключённые поля выделены синим цветом.
Вы должны быть осторожны, потому что браузер применяет стили валидации при загрузке страницы. В следующем примере каждое поле считается не прошедшим валидацию и содержит текст красного цвета и обведено красной рамкой ещё до того, как пользователь взаимодействовал с формой:
:invalid {
color: red;
border-color: red;
}
Желательно отображать сообщения об ошибках и выделять их цветом после того, как пользователь взаимодействовал с полем формы или попытался отправить всю форму.
Constrain Validation API
Constraint Validation API предоставляет параметры настройки, которые могут улучшить или изменить стандартное поведение проверки полей HTML5. Вы можете выполнять проверку после взаимодействия с пользователем, отображать определённые сообщения об ошибках или реализовать программную проверку, например подтвердить:
- поля нового пароля и подтверждения пароля совпадают
- одна дата следует за другой
- пользователь ввёл номер телефона, адрес электронной почты или и то, и другое. В следующих разделах описывается общий подход к Constrain Validation API в вашем коде.
1. Отключение проверки формы по умолчанию
Ваш код должен отключать валидацию формы по умолчанию и сообщения об ошибках, установив свойство атрибута <form>
noValidate = true
, например:
const myform = document.getElementById('myform');
myform.noValidate = true;
2. Добавление обработчика событий формы
Далее, вы должны добавить обработчик событий для отправки формы или изменения отдельных полей, например:
// валидация формы при отправке
myform.addEventListener('submit', validateForm);
Функция обработчик может проверить, что вся форма валидна используя методы элемента формы:
checkValidity()
— возвращаетtrue
, если все дочерние элементы соответствуют ограничениям и проходят валидацию.reportValidity()
— возвращаетtrue
, если дочерний элемент не подлежит валидации или соответствует ограничениям.
Обратите внимание, что оба метода вызывают событие invalid event
для каждого не валидного поля. Оно не всплывает, поэтому обработчики должны быть установлены по мере необходимости для каждого поля.
Эта простая функция обработчик останавливает отправку формы, когда одно или несколько полей не проходят валидацию:
// Валидация формы при отправке
function validateForm(e) {
const form = e.target;
if (!form.checkValidity()) {
// Форма не прошла валидацию - отменить отправку
e.preventDefault();
e.stopImmediatePropagation();
}
};
3. Валидация отдельных полей
Отдельные поля имеют следующие свойства и методы проверки ограничений:
willValidate
— Возвращаетtrue
, если элемент является кандидатом на участие в валидации.validationMessage
Сообщение проверки — пустая строка, если поле прошло валидацию.validity
—ValidityState
объект с проверенным свойство установленным вtrue
илиfalse
. Не прошедшие валидацию поля содержат одно или несколько из следующих свойств со значениемtrue
:
ValidityState | Описание |
---|---|
.badInput | браузер не может распознать введённые данные |
.customError | было установлено пользовательское сообщение о валидации |
.patternMismatch | значение не соответствует указанному шаблону атрибута |
.rangeOverflow | значение больше атрибута max |
.rangeUnderflow | значение меньше атрибута min |
.stepMismatch | значение не соответствует правилу атрибута step |
.tooLong | длинна строки больше значения атрибута maxlength |
.tooShort | длинна строки меньше значения атрибута minlength |
.typeMismatch | значение не соответствует валидному email или URL |
.valueMissing | требуемое значение пустое |
setCustomValidity()
— Устанавливает сообщение об ошибке для недопустимого поля. Установите пустою строку для валидного значения или оно останется не валидным навсегда.checkValidity()
— Возвращаетtrue
, если значениеinput
проходит валидацию. Оно похоже наvalidity
. Если значение не валидно вызывается событиеinvalid event
.
Функция-обработчик validateForm()
может пройтись по всем полям формы и применить класс invalid
к его родительскому элементу.
function validateForm(e) {
const
form = e.target,
field = Array.from(form.elements);
// применяем/удаляем класс invalid
field.forEach(i => {
if (i.checkValidity()) {
// поле валидно - удаляем класс
i.parentElement.classList.remove('invalid');
}
else {
// поле не валидно -- добавляем класс
i.parentElement.classList.add('invalid');
}
});
if (!form.checkValidity()) {
// форма не прошла валидацию - отменяем отправку
e.preventDefault();
e.stopImmediatePropagation();
}
};
Если вы определили обязательное поле email
в вашей html5 форме:
<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;
}
4. Добавление проверки пользовательского поля
В этой демонстрации на CodePen показан пример контактной формы с полями имени (обязательное поле), электронной почты и телефона. Валидация происходит при отправке, и форма считается валидной когда имя, адрес электронной почты и/или телефон содержат допустимые значения.
Функция validateForm()
:
- сбрасывает сообщение валидации и родительский стиль ошибки для каждого поля
- передаёт не пустую строку методу
.setCustomValidity()
поле электронной почты и телефона, если они не определены и, - применяет класс
invalid
к родительскому элементу всех недопустимых полей.
// проверка формы
function validateForm(e) {
const
form = e.target,
field = Array.from(form.elements);
// сброс полей
field.forEach(i => {
i.setCustomValidity('');
i.parentElement.classList.remove('invalid');
});
// email или телефон заданы?
const err = form.email.value || form.tel.value ? '' : 'error';
form.email.setCustomValidity(err);
form.tel.setCustomValidity(err);
if (!form.checkValidity()) {
// форма не прошла валидацию - отмена отправки
e.preventDefault();
e.stopImmediatePropagation();
// добавляем класс invalid
field.forEach(i => {
if (!i.checkValidity()) {
// поле не прошло валидацию - добавляем класс
i.parentElement.classList.add('invalid');
}
});
}
}
Резюме
Валидация формы может быть обыденной, но это необходимая деятельность веб-разработчика. Время написания собственных регулярных выражения для электронной почты и проверки введённых чисел давно прошло. Используйте стандартные типы input
, а затем, при необходимости проверяйте их с Constraint Validation API.
Никогда не забывайте проверять пользовательские данные на сервере!