Использование проверки HTML-форм и Constraint Validation API
Создание веб-форм всегда было сложной задачей. Хотя разметить саму форму легко, проверить, имеет ли каждое поле допустимое и согласованное значение, гораздо сложнее, а информирование пользователя о проблеме может стать настоящей головной болью. В HTML5 появились новые механизмы для форм: новые семантические типы элемента <input> и проверка ограничений, упрощающая проверку содержимого формы на стороне клиента. Простые стандартные ограничения можно проверять без JavaScript, задав новые атрибуты; более сложные ограничения можно проверять с помощью Constraint Validation API.
Основные сведения об этих понятиях с примерами см. в руководстве по проверке форм.
Примечание: Проверка ограничений HTML не отменяет необходимости проверки на серверной стороне. Хотя можно ожидать, что количество недопустимых запросов формы значительно уменьшится, их всё ещё можно отправить разными способами:
- Изменив HTML с помощью инструментов разработчика браузера.
- Составив HTTP-запрос вручную, не используя форму.
- Программно записав содержимое в форму (некоторые проверки ограничений выполняются только для пользовательского ввода, но не в случае, если задать значение поля формы с помощью JavaScript).
Поэтому всегда следует проверять данные формы на серверной стороне так же, как и на клиентской.
Встроенные и базовые ограничения
В HTML базовые ограничения задаются двумя способами:
- Выбором наиболее подходящего с семантической точки зрения значения для атрибута
typeэлемента<input>. Например, выбор типаemailавтоматически создаёт ограничение, проверяющее, является ли значение допустимым адресом электронной почты. - Заданием значений атрибутов, связанных с проверкой, что позволяет описывать базовые ограничения без использования JavaScript.
Семантические типы полей ввода
Встроенные ограничения для атрибута type таковы:
| Тип поля ввода | Описание ограничения | Соответствующее нарушение |
|---|---|---|
<input type="URL"> | Значение должно быть абсолютным URL-адресом, как определено в живом стандарте URL. | Нарушение ограничения TypeMismatch |
<input type="email"> | Значение должно быть синтаксически допустимым адресом электронной почты, обычно имеющим формат username@hostname.tld, но оно также может быть локальным, например username@hostname. | Нарушение ограничения TypeMismatch |
Для типа поля ввода email, если задан атрибут multiple, можно указать несколько значений в виде списка, разделённого запятыми. Если какое-либо значение в списке не удовлетворяет описанному здесь условию, возникает нарушение ограничения несоответствия типа.
Обратите внимание, что большинство типов полей ввода не имеют встроенных ограничений: некоторые из них исключены из проверки ограничений, а у других есть алгоритм очистки, преобразующий некорректные значения в правильное значение по умолчанию.
Атрибуты, связанные с проверкой
Помимо описанного выше атрибута type, для описания базовых ограничений используются следующие атрибуты:
| Атрибут | Типы полей ввода, поддерживающие атрибут | Допустимые значения | Описание ограничения | Соответствующее нарушение |
|---|---|---|---|---|
pattern | text, search, url, tel, email, password | Регулярное выражение JavaScript (скомпилированное с отключёнными флагами global, ignoreCase и multiline) | Значение должно соответствовать шаблону. | Нарушение ограничения patternMismatch |
min |
range, number
| Допустимое число | Значение должно быть больше или равно этому значению. | Нарушение ограничения rangeUnderflow |
date, month, week
| Допустимая дата | |||
datetime-local, time | Допустимые дата и время | |||
max |
range, number
| Допустимое число | Значение должно быть меньше или равно этому значению. | Нарушение ограничения rangeOverflow |
date, month, week
| Допустимая дата | |||
datetime-local, time | Допустимые дата и время | |||
required | text, search, url, tel, email, password, date, datetime-local, month, week, time, number, checkbox, radio, file; также для элементов <select> и <textarea> | отсутствует, поскольку это логический атрибут: его наличие означает true, отсутствие — false | Значение должно быть задано (если атрибут установлен). | Нарушение ограничения valueMissing |
step | date | Целое число дней | Если для шага не задано буквальное значение any, значение должно быть равно min + целому кратному шага. | Нарушение ограничения stepMismatch |
month | Целое число месяцев | |||
week | Целое число недель | |||
datetime-local, time | Целое число секунд | |||
range, number
| Целое число | |||
minlength | text, search, url, tel, email, password; также для элемента <textarea> | Целочисленная длина | Число символов (кодовых точек) должно быть не меньше значения атрибута, если оно не пустое. Все символы новой строки для <textarea> нормализуются до одного символа (в отличие от пар CRLF). | Нарушение ограничения tooShort |
maxlength | text, search, url, tel, email, password; также для элемента <textarea> | Целочисленная длина | Число символов (кодовых точек) не должно превышать значение атрибута. | Нарушение ограничения tooLong |
Процесс проверки ограничений
Проверка ограничений выполняется с помощью Constraint Validation API для отдельного элемента формы или на уровне формы, непосредственно для элемента <form>. Проверка ограничений выполняется следующими способами:
- Вызовом метода
checkValidity()илиreportValidity()интерфейса DOM, связанного с формой (HTMLInputElement,HTMLSelectElement,HTMLButtonElement,HTMLOutputElementилиHTMLTextAreaElement), который проверяет ограничения только для этого элемента и позволяет скрипту получить эту информацию. МетодcheckValidity()возвращает логическое значение, указывающее, соответствует ли значение элемента его ограничениям. (Обычно пользовательский агент делает это, определяя, какой из псевдоклассов CSS —:validили:invalid— применим.) В отличие от него, методreportValidity()сообщает пользователю о нарушениях ограничений. - Вызовом метода
checkValidity()илиreportValidity()интерфейсаHTMLFormElement. - Отправкой самой формы.
Вызов checkValidity() называется статической проверкой ограничений, а вызов reportValidity() или отправка формы — интерактивной проверкой ограничений.
Примечание:
- Если для элемента
<form>задан атрибутnovalidate, интерактивная проверка ограничений не выполняется. - Вызов метода
submit()интерфейсаHTMLFormElementне запускает проверку ограничений. Иными словами, этот метод отправляет данные формы на сервер, даже если они не соответствуют ограничениям. Вместо этого вызовите методclick()у кнопки отправки. - Ограничения
minlengthиmaxlengthпроверяются только для данных, введённых пользователем. Они не проверяются, если значение задано программно, даже при явном вызовеcheckValidity()илиreportValidity().
Сложные ограничения с помощью Constraint Validation API
С помощью JavaScript и Constraint API можно реализовать более сложные ограничения, например ограничения, объединяющие несколько полей или требующие сложных вычислений.
Основная идея заключается в том, чтобы запускать JavaScript при возникновении события в поле формы (например, onchange), вычислять, нарушено ли ограничение, а затем использовать метод field.setCustomValidity() для установки результата проверки: пустая строка означает, что ограничение выполнено, а любая другая строка указывает на ошибку и служит сообщением об ошибке, которое нужно показать пользователю.
Ограничение, объединяющее несколько полей: проверка почтового индекса
Формат почтового индекса различается в разных странах. Во многих странах допускается необязательный префикс с кодом страны (например, D- в Германии, F- во Франции и CH- в Швейцарии). В некоторых странах почтовые индексы состоят только из фиксированного числа цифр, а в других, например в Великобритании, используется более сложный формат, в котором в определённых позициях могут стоять буквы.
Примечание: Это не полноценная библиотека для проверки почтовых индексов, а лишь демонстрация основных понятий.
В качестве примера добавим скрипт, который проверяет ограничения формы:
<form>
<label for="postal-code">Postal Code: </label>
<input type="text" id="postal-code" />
<label for="country">Country: </label>
<select id="country">
<option value="ch">Switzerland</option>
<option value="fr">France</option>
<option value="de">Germany</option>
<option value="nl">The Netherlands</option>
</select>
<input type="submit" value="Validate" />
</form>
Он отображает следующую форму:
Сначала напишем функцию, проверяющую само ограничение:
const countrySelect = document.getElementById("country");
const postalCodeField = document.getElementById("postal-code");
function checkPostalCode() {
// For each country, defines the pattern that the postal code has to follow
const constraints = {
ch: [
"^(CH-)?\\d{4}$",
"Swiss postal codes must have exactly 4 digits: e.g. CH-1950 or 1950",
],
fr: [
"^(F-)?\\d{5}$",
"French postal codes must have exactly 5 digits: e.g. F-75012 or 75012",
],
de: [
"^(D-)?\\d{5}$",
"German postal codes must have exactly 5 digits: e.g. D-12345 or 12345",
],
nl: [
"^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$",
"Dutch postal codes must have exactly 4 digits, followed by 2 letters except SA, SD and SS",
],
};
// Read the country id
const country = countrySelect.value;
// Build the constraint checker
const constraint = new RegExp(constraints[country][0], "");
console.log(constraint);
// Check it!
if (constraint.test(postalCodeField.value)) {
// The postal code follows the constraint, we use the ConstraintAPI to tell it
postalCodeField.setCustomValidity("");
} else {
// The postal code doesn't follow the constraint, we use the ConstraintAPI to
// give a message about the format required for this country
postalCodeField.setCustomValidity(constraints[country][1]);
}
}
Затем свяжем её с событием change элемента <select> и событием input элемента <input>:
countrySelect.addEventListener("change", checkPostalCode);
postalCodeField.addEventListener("input", checkPostalCode);
Ограничение размера файла перед загрузкой
Ещё одно распространённое ограничение — ограничение размера загружаемого файла. Для проверки на стороне клиента до передачи файла на сервер необходимо объединить Constraint Validation API, в частности метод field.setCustomValidity(), с другим API JavaScript — в данном случае File API.
Вот HTML-часть:
<label for="fs">Select a file smaller than 75 kB: </label> <input type="file" id="fs" />
Она отображает:
JavaScript считывает выбранный файл, использует метод File.size() для получения его размера, сравнивает размер с (заданным в коде) пределом и вызывает Constraint API, чтобы сообщить браузеру о нарушении:
const fs = document.getElementById("fs");
function checkFileSize() {
const files = fs.files;
// If there is (at least) one file selected
if (files.length > 0) {
if (files[0].size > 75 * 1000) {
// Check the constraint
fs.setCustomValidity("The selected file must not be larger than 75 kB");
fs.reportValidity();
return;
}
}
// No custom constraint violation
fs.setCustomValidity("");
}
Наконец, свяжем метод с соответствующим событием:
fs.addEventListener("change", checkFileSize);
Визуальное оформление проверки ограничений
Помимо задания ограничений, веб-разработчики хотят контролировать сообщения, показываемые пользователям, и их оформление.
Управление внешним видом элементов
Внешним видом элементов можно управлять с помощью псевдоклассов CSS.
Псевдоклассы CSS :required и :optional
Псевдоклассы :required и :optional позволяют писать селекторы, соответствующие элементам формы, у которых есть атрибут required, или элементам, у которых его нет.
Псевдокласс CSS :placeholder-shown
См. :placeholder-shown.
Псевдоклассы CSS :valid и :invalid
Псевдоклассы :valid и :invalid используются для обозначения элементов <input>, содержимое которых проходит или не проходит проверку в соответствии с типом поля ввода. С помощью этих классов можно оформлять допустимые и недопустимые элементы формы, чтобы было легче определить, какие из них заполнены правильно, а какие — нет.
Управление текстом сообщения о нарушении ограничения
Управлять текстом сообщения о нарушении ограничения можно с помощью следующих средств:
-
Метод
setCustomValidity(message)для следующих элементов:-
<fieldset>. Примечание: установка пользовательского сообщения о допустимости для элементов fieldset в большинстве браузеров не предотвращает отправку формы. <input><output><select>- Кнопки отправки (созданные с помощью элемента
<button>с типомsubmitили элементаinputс типом submit). Кнопки других типов не участвуют в проверке ограничений. <textarea>
-
-
Интерфейс
ValidityStateописывает объект, возвращаемый свойствомvalidityперечисленных выше типов элементов. Он представляет различные причины, по которым введённое значение может быть недопустимым. Вместе они помогают объяснить, почему значение элемента не проходит проверку.
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation