validity.state вместо if-ов: браузер валидирует формы на лету без костылей
-
Устал от кучи if-else в обработчиках форм? Браузер уже всё проверит сам через validity.state. Это объект с флагами ошибок, который обновляется на лету без твоего JS.
Забудь ручные проверки на пустоту, длину или паттерны. Атрибуты HTML типа required, minlength, pattern сами генерируют состояния :valid и :invalid. Получаешь чистый код, меньше багов и ноль зависимостей. Разберём, как это работает под капотом и почему мидлы всё равно пишут костыли.
Как validity.state ловит ошибки без твоего кода
Браузерный движок следит за каждым вводом и обновляет validity - объект с булевыми флагами. Там valueMissing для required, tooShort для minlength, patternMismatch для regex. Всё это живое: ввёл букву - флаг переключился.
Не нужно oninput с if (value.length < 5). Браузер сам решает, валидно или нет, и вешает :invalid. Плюс checkValidity() вернёт true/false для всей формы. А setCustomValidity() позволит подправить сообщение, если надо кастом.
Это решает типичные грабли: утечки в ивент-лупе от лишних слушателей, несинхронные проверки при submit. Вместо 50 строк JS - пара атрибутов в HTML.
- valueMissing: true, если required-поле пустое. Браузер блочит submit.
- typeMismatch: для email/number - ввёл буквы в цифры? Флаг взлетел.
- tooLong/tooShort: min/maxlength сами считают символы, без твоих счётчиков.
- patternMismatch: regex в pattern атрибуте - браузер парсит нативно.
- valid: итоговый флаг. true только если все остальные false.
Состояние Псевдокласс Пример атрибута Что блочит Пустое required :invalid required submit Короткий текст :invalid minlength=“5” флаг tooShort Не email :invalid type=“email” typeMismatch Соответствует :valid pattern=“[a-z]+” submit OK Подключаем CSS для состояний: стили без JS
Псевдоклассы :valid и :invalid - это готовый API для стилей. input:invalid { border: 2px solid red; } - и поле краснеет на лету. Добавь :required для фокуса на обязательных.
form:invalid блокирует кнопку: button[type=submit] { opacity: 0.5; pointer-events: none; } form:valid button { opacity: 1; pointer-events: auto; }. Никаких MutationObserver или ResizeObserver - чистый CSS.
Новички пишут onblur с классами error/success, но это бандл разрастается. Браузер уже знает состояние, зачем дублировать? Минус один слушатель на поле.
- input:invalid: красная обводка + shake-анимация для фидбека.
- input:valid + input:focus:valid: зелёный чекмарк через ::after.
- form:invalid ~ button: disable до полной валидности формы.
- :out-of-range: для number min/max - стилизуй отдельно.
input:invalid { border-color: #e74c3c; animation: shake 0.5s; } input:valid { border-color: #27ae60; } form:invalid button { background: #bdc3c7; cursor: not-allowed; }JS только для тонкой настройки: checkValidity и кастом
Хочешь свои сообщения? validity.validationMessage - стоковое от браузера. Перезапиши через setCustomValidity(‘Минимум 8 символов, бро’). Вызывай в oninput или после debounce.
reportValidity() покажет все ошибки диалогом - браузер сам. Для a11y: aria-invalid=“true” на invalid полях, aria-errormessage ссылается на спан с текстом.
Без JS форма валидна по дефолту, но мидлы добавляют preventDefault и циклы по полям. validity.state избавляет от этого: if (!form.checkValidity()) return; - и всё.
- reportValidity(): браузерный popup со всеми ошибками.
- setCustomValidity(‘’): сбрасывает кастом, возвращает к нативному.
- aria-invalid связывается с validity.valid автоматически в новых браузерах.
- CustomError: validity.customError для твоих флагов.
Метод Что делает Когда юзать checkValidity() true/false для поля/формы перед submit reportValidity() Показывает ошибки UI onsubmit fallback setCustomValidity() Кастом текст ошибки после async чека Грабли с validity, которые бьют мидлов
Не все флаги работают везде: customError игнорирует :invalid, пока не вызовешь checkValidity. pattern на type=search может глючить в старых Safari.
willValidate false для disabled/readonly - браузер пропускает. rangeUnderflow/Overflow для number - забудь про ручной парсинг Int.
Мидлы пишут глобальные валидаторы с Lodash, но validity.state - 0kb, нативно. Тестируй: console.log(input.validity) - увидишь все флаги живьём.
- rangeOverflow: > max в number - браузер ловит.
- stepMismatch: не кратно step в range.
- validLength: false при mismatch min/maxlength.
Нативка рулит, но кастом всё равно нужен
validity.state - идеал для 80% форм: регистрация, поиск, фильтры. JS только для серверного чека или сложных правил типа уникальности email.
Осталось async: подожди API, потом setCustomValidity на основе ответа. Или polyfill для IE, но кто его юзает в 2026? Думай о производительности: меньше JS - быстрее ивент-луп.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.