HTML5 валидация
С появлением HTML5, урааа, появились нативные средства валидации. С помощью html атрибутов можно указать, как проверять то или иное поле, большинство разработчиков их знает и использует. Например:
- required - поле станет обязательным для заполнения;
- minlength - нельзя будет ввести значения, меньше заданной длины;
- pattern - задает регулярное выражение для проверки значения поля.
С полным списком можно ознакомиться здесь https://www.w3schools.com/html/html_form_attributes.asp
А с помощью псевдоклассов :valid и :invalid, в css можно подсветить корректное / некорректное поле. Также в атрибуте title поля формы для проверки паттерном можно поменять текст предупреждения.
Вроде бы это должно помочь с клиентской проверкой форм, прощайте костыли и плагины, но работает это иногда странно.. Например, minlength вообще не поддерживается IE и EDGE (ох уж эти майкрософт). А пустое поле с атрибутом required не помешает сделать сабмит формы в сафари.
Но самое главное, системные сообщения всегда выглядят по-разному
IE/EDGE:
Firefox:
Google Chrome:
В итоге нет кастомизации. Как видим эти сообщения могут перекрыть наши сообщения или другие элементы, также могут не устроить клиента, могут не сочетаться с дизайном. И казалось бы все, нет повсеместного применения нативной валидации, но…
Constraint Validation API
Суть в том, что каждое поле нативно хранит состояние валидности по совершенно разным параметрам, и это все отслеживается в JS без подключения сторонних библиотек, и этот API работает везде, разве с небольшими недочетами в IE и EDGE.
Как его использовать?
Изначально придется кое-чем пожертвовать, и разрешить отправить неправильную форму для отключения системных сообщений с помощью атрибута формы novalidate.
novalidate:
- отключает системные сообщения;
- сохраняет состояния валидности (JS, CSS);
- позволяет отправить форму.
Саму логику валидации предлагаю обернуть в маленькую функцию-библиотеку.
Создание библиотеки
Наша функция на вход будет принимать три параметра:
- formSelector - формы, которые будем валидировать;
- setError - функция, которая будет выделять поле с ошибкой;
- deleteError - функция, которая будет выделять поле, заполненное успешно.
1) Отключим системные уведомления об ошибках для выбранных форм, и найдем в них поля.
2) Создадим массив атрибутов, по которым будем валидировать поля
Кратко о атрибутах валидации:
- badInput - указывает, есть ли данные, которые браузер вообще не может преобразовать (нет поддержки IE11);
- patternMismatch - указывает, соответствуют ли данные паттерну, заданным в атрибуте pattern;
- rangeOverflow - указывает, превышает ли значение максимальное, заданное в атрибуте max;
- rangeUnderflow - указывает, превышает ли значение минимальное, заданное в атрибуте min;
- stepMismatch - указывает, соответствует ли значение правилам, определенным атрибутом step (то есть не равномерно делится на значение шага);
- tooLong - указывает, превышает ли длина значение максимальное, заданное в атрибуте maxlength;
- tooShort - указывает, превышает ли длина значение минимальное, заданное в атрибуте minlength (Не работает в IE/EDGE, проверку можно сделать через паттерн);
- typeMismatch - указывает, соответствует ли значение типу, заданному в атрибуте type;
- valueMissing - указывает, не пустое ли значение, работает с помощью required;
- valid - указывает, что поле валидно учитывая все ограничения.
https://developer.mozilla.org/ru/docs/Web/API/ValidityState - здесь оригинал
3) Создадим функцию, которая будет проверять поле по каждому атрибуту валидности
То есть здесь в цикле по каждому состоянию в отдельности проверяем поле, и для каждого состояния можем сделать необходимую манипуляцию. Например несоответствие типу обработать одним образом, а пустоту другим. Такие действия можно совершать, например, при снятии фокуса и перед submit.
4) Вызов проверки валидации
В данном случае, предлагаю валидировать поля при расфокусировке
5) Проверка всей формы
А саму функцию проверки формы вернем нашей библиотекой
Завершение
Могли заметить, что мы использовали, современный стандарты JS - ES6+, который не поддерживается в IE. Для решения этого момента и для того, чтобы библиотека меньше весила, прогоним ее через webpack+babel.
Результат
https://github.com/perryutkonos/validator/ - библиотека с примером
https://github.com/perryutkonos/validator/tree/master/src/index.js - исходник библиотеки
https://github.com/perryutkonos/validator/tree/master/dist - готовая библиотека
https://github.com/perryutkonos/validator/tree/master/example - пример интеграции
https://perryutkonos.github.io/validator/example/ - демо примера
P.S. Прошу рассматривать эту библиотеку как учебный материал и заготовку для реальных задач. Здесь могут быть не учтены все моменты.
Итого
Мы можем, используя только стандартные атрибуты, только с проверкой состояния (без считывания значений из формы, проверки их на регулярку, пустоту и прочего в скрипте), сделать очень гибкую кастомизируемую валидацию.