API ограничений проверки JavaScript
Изучите HTML5 Constraint Validation API в JavaScript: checkValidity, reportValidity, setCustomValidity, объект ValidityState, пользовательские сообщения об ошибках, проверка по шаблону и валидация форм в реальном времени.
JavaScript — неотъемлемый язык веб-разработки, обеспечивающий динамическое содержимое и улучшенное взаимодействие с пользователем. Важнейшим аспектом JavaScript в веб-формах является HTML5 Constraint Validation API. В этом руководстве подробно рассматривается API — его методы, объект ValidityState, а также способы создания пользовательских сообщений и обратной связи в реальном времени — с практическими примерами как для начинающих, так и для опытных разработчиков.
Эта страница опирается на материалы работы с формами в DOM и события и метода submit. Если вам нужно прочитать или отправить данные формы после их проверки, см. свойства и методы формы и FormData.
Введение в HTML5 Constraint Validation API
HTML5 Constraint Validation API обеспечивает нативную клиентскую проверку элементов форм, обнаруживая ошибки до отправки формы. Ограничения задаются прямо в HTML с помощью таких атрибутов, как required, type="email", min, max, minlength, maxlength, step и pattern. Браузер автоматически применяет их и предоставляет доступ к ним через JavaScript, позволяя настраивать поведение.
Клиентская проверка делает формы отзывчивыми и сокращает количество лишних запросов к серверу. Однако она не является защитным барьером — пользователь может полностью обойти её, отключив JavaScript или создав собственный запрос. Всегда выполняйте повторную проверку на сервере.
Интерфейс Constraint Validation API
Каждый элемент формы (<input>, <textarea>, <select>, <button>, <fieldset> и сама <form>) предоставляет один и тот же небольшой набор членов.
Методы
element.checkValidity()— возвращаетtrue, если элемент удовлетворяет всем ограничениям, иначеfalse. При неудаче также генерирует событиеinvalidна элементе.element.reportValidity()— аналогичноcheckValidity(), но дополнительно отображает нативное всплывающее сообщение об ошибке браузера для первого недействительного поля. Полезно, когда нужен нативный UI без пользовательского сообщения.element.setCustomValidity(message)— задаёт пользовательскую строку ошибки. Непустая строка делает элемент недействительным; пустая строка ('') сбрасывает пользовательскую ошибку и позволяет элементу снова быть действительным.form.checkValidity()/form.reportValidity()— проверяют сразу все элементы управления в форме.
Свойства
element.validity— объектValidityStateтолько для чтения, описывающий причину недействительности поля.element.validationMessage— локализованное сообщение, которое браузер отобразил бы для текущего недействительного состояния (пустое, когда поле действительно).element.willValidate—true, если элемент будет проверяться при валидации (отключённые поля и поляreadonlyпропускаются).
Объект ValidityState
element.validity предоставляет boolean для каждого вида нарушения, а также valid:
| Свойство | true когда… |
|---|---|
valueMissing | обязательное поле (required) пустое |
typeMismatch | значение имеет неверный тип (например, некорректный type="email") |
patternMismatch | значение не соответствует атрибуту pattern |
tooShort / tooLong | значение короче/длиннее minlength/maxlength |
rangeUnderflow / rangeOverflow | число/дата меньше min или больше max |
stepMismatch | значение не соответствует шагу step |
customError | setCustomValidity() получил непустое сообщение |
valid | поле удовлетворяет всем ограничениям |
Анализируя эти флаги, можно адаптировать сообщение к конкретной проблеме:
const input = document.querySelector('#age');
const v = input.validity;
if (v.valueMissing) {
input.setCustomValidity('Age is required.');
} else if (v.rangeUnderflow) {
input.setCustomValidity('You must be at least 18.');
} else {
input.setCustomValidity(''); // clears the custom error
}Настройка первой проверки
Прежде чем переходить к сложным правилам, начните с основ: проверьте, что обязательное поле (required) не пустое.
Добавление атрибута novalidate к форме отключает стандартный UI проверки браузера. Constraint Validation API по-прежнему работает в JavaScript — checkValidity() и validity остаются точными — так что вы можете реализовать собственную обратную связь, подавив нативные всплывающие подсказки.
<form id="registrationForm" novalidate>
<label for="username">Username:</label>
<input type="text" id="username" required />
<button type="submit">Register</button>
<span id="usernameError" style="color: red;"></span>
<span id="registerSuccess" style="color: green; display: none;">Registration successful!</span>
</form>
<script>
document.getElementById('registrationForm').addEventListener('submit', function(event) {
event.preventDefault();
const input = document.getElementById('username');
const usernameError = document.getElementById('usernameError');
const registerSuccess = document.getElementById('registerSuccess');
if (!input.checkValidity()) {
usernameError.textContent = 'Username is required.';
registerSuccess.style.display = 'none'; // Hide success message if visible
} else {
usernameError.textContent = ''; // Clear error message
registerSuccess.textContent = 'Registration successful!';
registerSuccess.style.display = 'block'; // Show success message
input.value = ''; // Reset the username input
}
});
</script>Этот фрагмент кода демонстрирует базовую настройку, в которой проверка input.checkValidity() используется для обеспечения обязательности поля. Форма выдаст сообщение об ошибке, если поле имени пользователя оставлено пустым.
Реализация пользовательских сообщений об ошибках
Выйдя за рамки стандартных сообщений браузера, можно создать более органичный пользовательский опыт, отображая пользовательские сообщения об ошибках непосредственно в HTML-разметке. Вот как это реализовать:
Обратите внимание, что стандартная HTML5 проверка email может не требовать домена верхнего уровня, позволяя пропускать значения вроде w3docs@aol. Чтобы гарантировать наличие домена в адресах электронной почты, мы добавили более строгий шаблон .+@.+\..+ к полю email. Это регулярное выражение требует наличия хотя бы одной точки после символа @, что точнее соответствует реальным форматам email. (Чтобы изучить синтаксис регулярных выражений, используемых в шаблонах, см. якоря для начала и конца строки.)
<form id="contactForm" novalidate>
<label for="email">Email:</label>
<input type="email" id="email" pattern=".+@.+\..+" required />
<button type="submit">Submit</button>
<span id="emailError" style="color: red"></span>
<span id="successMessage" style="color: green; display: none;">Submission successful!</span>
</form>
<script>
document.getElementById("contactForm").addEventListener("submit", function (event) {
event.preventDefault(); // Prevent default form submission
const email = document.getElementById("email");
const errorMessage = document.getElementById("emailError");
const successMessage = document.getElementById("successMessage");
if (!email.checkValidity()) {
errorMessage.textContent = "Please enter a valid email address, including a domain."; // Display custom error message
successMessage.style.display = "none"; // Hide success message if visible
} else {
errorMessage.textContent = ""; // Clear the error message
successMessage.textContent = "Submission successful!";
successMessage.style.display = "block"; // Show success message
email.value = ""; // Reset the email input
}
});
</script>Этот код улучшает пользовательский опыт, обеспечивая немедленную встроенную обратную связь о корректности введённого адреса электронной почты.
Улучшение проверки форм с помощью шаблонов
Иногда требуются более специфичные проверки, например, убедиться, что ввод соответствует определённому шаблону. Это часто применяется для номеров телефонов, почтовых индексов и подобных полей. Атрибут pattern неявно привязан к якорям — всё значение должно соответствовать шаблону — поэтому [0-9]{3}-[0-9]{3}-[0-9]{4} принимает 123-456-7890, но отклоняет 1234567890.
<form id="signupForm" novalidate>
<label for="phone">Phone (XXX-XXX-XXXX):</label>
<input type="tel" id="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required />
<button type="submit">Sign Up</button>
<span id="phoneError" style="color:red;"></span>
<span id="successMessage" style="color:green; display:none;">Submission successful!</span>
</form>
<script>
document.getElementById('signupForm').addEventListener('submit', function(event) {
const phone = document.getElementById('phone');
const phoneError = document.getElementById('phoneError');
const successMessage = document.getElementById('successMessage');
if (!phone.checkValidity()) {
phoneError.textContent = 'Please enter a phone number in the format XXX-XXX-XXXX.';
successMessage.style.display = 'none'; // Hide success message if present
} else {
phoneError.textContent = '';
phone.value = ''; // Reset the input field
successMessage.textContent = 'Submission successful!';
successMessage.style.display = 'block'; // Show success message
}
});
</script>В этом примере атрибут pattern используется для указания того, что номер телефона должен соответствовать определённому формату, повышая качество данных, собираемых через форму.
Проверка в реальном времени с объектом ValidityState
Ожидание до момента отправки может казаться медленным. Прослушивая событие input и считывая флаги validity, можно давать обратную связь по мере ввода и формировать сообщение о конкретной ошибке:
<form id="profileForm" novalidate>
<label for="user">Username (3-12 letters/digits):</label>
<input type="text" id="user" pattern="[A-Za-z0-9]{3,12}" required />
<span id="userMsg" style="color:red;"></span>
</form>
<script>
const user = document.getElementById('user');
const msg = document.getElementById('userMsg');
user.addEventListener('input', function () {
const v = user.validity;
if (v.valueMissing) {
msg.textContent = 'Username is required.';
} else if (v.patternMismatch) {
msg.textContent = 'Use 3-12 letters or digits only.';
} else {
msg.textContent = ''; // valid
}
});
</script>Здесь valueMissing и patternMismatch берутся напрямую из объекта ValidityState, поэтому один обработчик сообщает точную причину без необходимости вручную переопределять правила проверки.
Сочетание декларативных и пользовательских правил
Некоторые проверки — например, «пароли должны совпадать» — нельзя выразить с помощью HTML-атрибутов. Используйте setCustomValidity(), чтобы включить их в тот же процесс проверки:
const password = document.getElementById('password');
const confirm = document.getElementById('confirm');
confirm.addEventListener('input', function () {
if (confirm.value !== password.value) {
confirm.setCustomValidity('Passwords do not match.');
} else {
confirm.setCustomValidity(''); // clear so the field becomes valid
}
});Поскольку пользовательская ошибка участвует в checkValidity(), обработчик отправки формы не требует особой обработки — несовпадающее поле просто сообщает о недействительности, как и любое другое.
Заключение
HTML5 Constraint Validation API — мощный инструмент для веб-разработчиков, желающих реализовать клиентскую проверку форм. Он не только улучшает пользовательский опыт, обеспечивая немедленную обратную связь, но и снижает нагрузку на сервер. Следуя примерам из этого руководства, вы сможете создавать более надёжные, эффективные и удобные для пользователя веб-формы. Для получения обратной связи в реальном времени рассмотрите возможность прослушивания событий input или change наряду с обработчиком отправки формы.