Задача
СкопированоКто из нас не знаком с той неприятной ситуацией, когда усердно заполняешь форму, вводишь данные, а потом, с надеждой нажимая на кнопку «Отправить», обнаруживаешь, что что-то пошло не так и все усилия пропали даром? Для этого есть решение — мгновенная валидация при помощи JavaScript!
Отличный пользовательский опыт — ключ к успеху. Валидация форм с помощью HTML не может предоставить того уровня UX (пользовательского опыта), который требуется стандартами веб-разработки. Ему на помощь приходит валидация через JavaScript. Она обеспечивает мгновенную обратную связь при заполнении формы и аккуратно подсказывает, что нужно исправить прежде чем форма отправится.
Готовое решение
СкопированоПример стандартной HTML-разметки формы:
<form class="form" name="form" method="POST" novalidate> <div class="form__field-container"> <label class="form__field"> <span class="form__label">Имя:</span> <input type="text" id="input__name" class="form__type-input" placeholder="Иван" pattern="^[a-zA-Zа-яА-ЯЁё \-]+$" data-error-message="Разрешены символы латиницы, кириллицы, знаки дефиса и пробелы." aria-describedby="name-error" required > </label> <span class="form__error input__name-error" id="name-error" aria-live="polite" > </span> </div> <div class="form__field-container"> <label class="form__field"> <span class="form__label">Фамилия:</span> <input type="text" id="input__surname" class="form__type-input" placeholder="Васильевич" pattern="^[a-zA-Zа-яА-ЯЁё\s\-]+$" data-error-message="Разрешены символы латиницы, кириллицы, знаки дефиса и пробелы." aria-describedby="surname-error" required > </label> <span class="form__error input__surname-error" id="surname-error" aria-live="polite" > </span> </div> <div class="form__field-container"> <label class="form__field"> <span class="form__label">Почта:</span> <input type="email" id="input__e-mail" class="form__type-input" placeholder="menyaet.professiyu@ivan.com" aria-describedby="email-error" required > </label> <span class="form__error input__e-mail-error" id="email-error" aria-live="polite" > </span> </div> <div class="form__field-container"> <label class="form__field"> <span class="form__label">Возраст:</span> <input type="number" id="input__age" class="form__type-input" placeholder="40" min="18" max="100" aria-describedby="age-error" required > </label> <span class="form__error input__age-error" id="age-error" aria-live="polite" > </span> </div> <div class="form__field-container"> <label class="form__checkbox-label"> <input type="checkbox" id="input__checkbox" class="form__type-checkbox" checked aria-describedby="checkbox-error" required /> <span class="form__type-checkbox-title"> Я согласен быть царём </span> </label> <span class="form__error input__checkbox-error" id="checkbox-error" aria-live="polite"></span> </div> <button type="submit" class="button" aria-describedby="empty-error" > Отправить </button> <span class="form__empty-error" id="empty-error" aria-live="assertive" > </span></form>
<form
class="form"
name="form"
method="POST"
novalidate
>
<div class="form__field-container">
<label class="form__field">
<span class="form__label">Имя:</span>
<input
type="text"
id="input__name"
class="form__type-input"
placeholder="Иван"
pattern="^[a-zA-Zа-яА-ЯЁё \-]+$"
data-error-message="Разрешены символы латиницы,
кириллицы, знаки дефиса и пробелы."
aria-describedby="name-error"
required
>
</label>
<span
class="form__error
input__name-error"
id="name-error"
aria-live="polite"
>
</span>
</div>
<div class="form__field-container">
<label class="form__field">
<span class="form__label">Фамилия:</span>
<input
type="text"
id="input__surname"
class="form__type-input"
placeholder="Васильевич"
pattern="^[a-zA-Zа-яА-ЯЁё\s\-]+$"
data-error-message="Разрешены символы латиницы,
кириллицы, знаки дефиса и пробелы."
aria-describedby="surname-error"
required
>
</label>
<span
class="form__error
input__surname-error"
id="surname-error"
aria-live="polite"
>
</span>
</div>
<div class="form__field-container">
<label class="form__field">
<span class="form__label">Почта:</span>
<input
type="email"
id="input__e-mail"
class="form__type-input"
placeholder="menyaet.professiyu@ivan.com"
aria-describedby="email-error"
required
>
</label>
<span
class="form__error input__e-mail-error"
id="email-error"
aria-live="polite"
>
</span>
</div>
<div class="form__field-container">
<label class="form__field">
<span class="form__label">Возраст:</span>
<input
type="number"
id="input__age"
class="form__type-input"
placeholder="40"
min="18"
max="100"
aria-describedby="age-error"
required
>
</label>
<span
class="form__error input__age-error"
id="age-error"
aria-live="polite"
>
</span>
</div>
<div class="form__field-container">
<label class="form__checkbox-label">
<input
type="checkbox"
id="input__checkbox"
class="form__type-checkbox"
checked
aria-describedby="checkbox-error"
required
/>
<span class="form__type-checkbox-title">
Я согласен быть царём
</span>
</label>
<span class="form__error input__checkbox-error" id="checkbox-error" aria-live="polite"></span>
</div>
<button
type="submit"
class="button"
aria-describedby="empty-error"
>
Отправить
</button>
<span
class="form__empty-error"
id="empty-error"
aria-live="assertive"
>
</span>
</form>
Код JavaScript для валидации всех полей формы:
const form = document.querySelector('.form')const inputList = Array.from(form.querySelectorAll('.form__type-input'))const checkboxElement = form.querySelector('.form__type-checkbox')const buttonElement = form.querySelector('.button')const formErrorElement = form.querySelector('.form__empty-error')startValidation()function startValidation() { toggleButton() form.addEventListener('submit', (event) => { event.preventDefault() if (hasInvalidInput()) { formError() inputList.forEach((inputElement) => { checkInputValidity(inputElement) toggleInputError(inputElement) }) toggleInputError(checkboxElement) } }) inputList.forEach((inputElement) => { inputElement.addEventListener('input', () => { checkInputValidity(inputElement) toggleButton() }) inputElement.addEventListener('blur', () => { toggleInputError(inputElement) }) inputElement.addEventListener('focus', () => { toggleErrorSpan(inputElement) }) checkboxElement.addEventListener('change', () => { toggleInputError(checkboxElement) toggleButton() }) })}function checkInputValidity(inputElement) { if (inputElement.validity.patternMismatch) { inputElement.setCustomValidity(inputElement.dataset.errorMessage) } else { inputElement.setCustomValidity(checkLengthMismatch(inputElement)) }}function checkLengthMismatch(inputElement) { if (inputElement.type !== 'text') { return '' } const valueLength = inputElement.value.trim().length if (valueLength < inputElement.minLength) { return `Минимальное количество символов: ${inputElement.minLength}` } return ''}function hasInvalidInput() { return ( inputList.some(inputElement => !inputElement.validity.valid) || !checkboxElement.validity.valid )}function toggleErrorSpan(inputElement, errorMessage){ const errorElement = document.querySelector(`.${inputElement.id}-error`) if (errorMessage) { inputElement.classList.add('form__type-input-error') errorElement.textContent = errorMessage errorElement.classList.add('form__error-active') } else { inputElement.classList.remove('form__type-input-error') errorElement.textContent = '' errorElement.classList.remove('form__error-active') }}function toggleButton() { if (hasInvalidInput()) { buttonElement.classList.add('button-inactive') buttonElement.setAttribute('aria-disabled', 'true') } else { buttonElement.classList.remove('button-inactive') buttonElement.setAttribute('aria-disabled', 'false') formErrorElement.textContent = '' }}function formError() { const errorMessage = 'Заполните все поля для отправки формы.' formErrorElement.textContent = errorMessage}
const form = document.querySelector('.form')
const inputList = Array.from(form.querySelectorAll('.form__type-input'))
const checkboxElement = form.querySelector('.form__type-checkbox')
const buttonElement = form.querySelector('.button')
const formErrorElement = form.querySelector('.form__empty-error')
startValidation()
function startValidation() {
toggleButton()
form.addEventListener('submit', (event) => {
event.preventDefault()
if (hasInvalidInput()) {
formError()
inputList.forEach((inputElement) => {
checkInputValidity(inputElement)
toggleInputError(inputElement)
})
toggleInputError(checkboxElement)
}
})
inputList.forEach((inputElement) => {
inputElement.addEventListener('input', () => {
checkInputValidity(inputElement)
toggleButton()
})
inputElement.addEventListener('blur', () => {
toggleInputError(inputElement)
})
inputElement.addEventListener('focus', () => {
toggleErrorSpan(inputElement)
})
checkboxElement.addEventListener('change', () => {
toggleInputError(checkboxElement)
toggleButton()
})
})
}
function checkInputValidity(inputElement) {
if (inputElement.validity.patternMismatch) {
inputElement.setCustomValidity(inputElement.dataset.errorMessage)
} else {
inputElement.setCustomValidity(checkLengthMismatch(inputElement))
}
}
function checkLengthMismatch(inputElement) {
if (inputElement.type !== 'text') {
return ''
}
const valueLength = inputElement.value.trim().length
if (valueLength < inputElement.minLength) {
return `Минимальное количество символов: ${inputElement.minLength}`
}
return ''
}
function hasInvalidInput() {
return (
inputList.some(inputElement => !inputElement.validity.valid) || !checkboxElement.validity.valid
)
}
function toggleErrorSpan(inputElement, errorMessage){
const errorElement = document.querySelector(`.${inputElement.id}-error`)
if (errorMessage) {
inputElement.classList.add('form__type-input-error')
errorElement.textContent = errorMessage
errorElement.classList.add('form__error-active')
} else {
inputElement.classList.remove('form__type-input-error')
errorElement.textContent = ''
errorElement.classList.remove('form__error-active')
}
}
function toggleButton() {
if (hasInvalidInput()) {
buttonElement.classList.add('button-inactive')
buttonElement.setAttribute('aria-disabled', 'true')
} else {
buttonElement.classList.remove('button-inactive')
buttonElement.setAttribute('aria-disabled', 'false')
formErrorElement.textContent = ''
}
}
function formError() {
const errorMessage = 'Заполните все поля для отправки формы.'
formErrorElement.textContent = errorMessage
}
CSS-стили, которые будут использоваться при валидации:
/* Для изменения цвета обводки элемента формы при валидации */.form__type-input-error { border: 1px solid #FF8630; background-color: rgb(255 134 48 / 0.1);}/* Для отображения span-элемента с ошибкой */.form__error-active { display: block;}/* Для блокировки кнопки submit */.button-inactive { cursor: default; background-color: rgb(211 211 211 / 0.6);}
/* Для изменения цвета обводки элемента формы при валидации */
.form__type-input-error {
border: 1px solid #FF8630;
background-color: rgb(255 134 48 / 0.1);
}
/* Для отображения span-элемента с ошибкой */
.form__error-active {
display: block;
}
/* Для блокировки кнопки submit */
.button-inactive {
cursor: default;
background-color: rgb(211 211 211 / 0.6);
}
Разбор решения
СкопированоСначала сообщаем браузеру, что он не должен валидировать форму стандартным способом, добавляя атрибут novalidate к тегу <form>.
<form class="form__field" novalidate> <!-- Содержимое формы --></form>
<form class="form__field" novalidate>
<!-- Содержимое формы -->
</form>
Разметка
СкопированоВзгляните на пример разметки элемента формы, чтобы лучше понять, как осуществляется валидация.
Добавим атрибуты:
type— определяет ожидаемый тип данных в поле.placeholder— предоставляет подсказку пользователю о том, какие данные нужно ввести.required— указывает на обязательность заполнения поля.
Свяжем поле ввода и <span> с ошибкой с помощью идентификаторов и классов CSS. Задаём идентификатор для <input> и присваиваем для <span> аналогичный класс, добавляя '-error' в конце. Это позволит найти <span> в DOM по такой схеме: document. Чтобы эта связь между полем и ошибкой к нему была понятна и пользователям вспомогательных технологий, свяжем их атрибутом aria у поля и кнопки и id с таким же значением у <span>. Чтобы вспомогательные технологии рассказывали о них автоматически, добавим ещё другой ARIA-атрибут aria.
Настроим параметры валидации. Тут можно использовать как стандартные атрибуты — maxlength/minlength, так и нестандартные атрибуты типа pattern с регулярными выражениями. Последний позволяет настроить более точные и специфические правила для полей ввода.
Подробнее о pattern: хотя в большинстве случаев стандартных сообщений валидации достаточно, иногда возникает необходимость в более специфических требованиях к полям ввода. Возьмём, к примеру, ситуацию, когда требуется ввод только букв латиницы и кириллицы, дефисов и пробелов. Такой набор символов не предусмотрен стандартной валидацией, что делает необходимым использование кастомной валидации. Для этого используем регулярное выражение и записываем кастомное сообщение об ошибке в специально созданный data-атрибут — 'data-error-message'. Подробнее о data-атрибутах можно прочитать в доке про атрибуты data.
<label class="form__field"> <span class="form__label">Имя:</span> <input type="text" id="input__name" class="form__type-input" placeholder="Иван" pattern="^[a-zA-Zа-яА-ЯЁё \-]+$" data-error-message="Разрешены символы латиницы, кириллицы, знаки дефиса и пробелы." aria-describedby="name-error" required ></label><span class="form__error input__name-error" id="name-error" aria-live="polite"></span>
<label class="form__field">
<span class="form__label">Имя:</span>
<input
type="text"
id="input__name"
class="form__type-input"
placeholder="Иван"
pattern="^[a-zA-Zа-яА-ЯЁё \-]+$"
data-error-message="Разрешены символы латиницы,
кириллицы, знаки дефиса и пробелы."
aria-describedby="name-error"
required
>
</label>
<span
class="form__error
input__name-error"
id="name-error"
aria-live="polite"
>
</span>
JavaScript
СкопированоСначала собираем все необходимые DOM-элементы для валидации:
const form = document.querySelector('.form')const inputList = Array.from(form.querySelectorAll('.form__type-input'))const checkboxElement = form.querySelector('.form__type-checkbox')const buttonElement = form.querySelector('.button')const formErrorElement = form.querySelector('.form__empty-error')
const form = document.querySelector('.form')
const inputList = Array.from(form.querySelectorAll('.form__type-input'))
const checkboxElement = form.querySelector('.form__type-checkbox')
const buttonElement = form.querySelector('.button')
const formErrorElement = form.querySelector('.form__empty-error')
Функция start инициирует процесс валидации. Она добавляет обработчик событий для всей формы на событие submit, где используется event для предотвращения стандартного поведения формы при отправке. Для дополнительной информации читайте «Работа с формами».
На каждое поле ввода назначаются обработчики событий input, blur и focus. При любых изменениях в полях ввода активируются функции check и toggle. При потере фокуса активируется функция toggle, а при установке фокуса сбрасывается сообщение об ошибке с помощью toggle.
Для чекбокса добавим отдельный обработчик change, при срабатывании такого события вызовутся функции toggle и toggle. Все эти функции мы напишем далее.
function startValidation() { form.addEventListener('submit', (event) => { event.preventDefault() if (hasInvalidInput()) { formError() inputList.forEach((inputElement) => { checkInputValidity(inputElement) toggleInputError(inputElement) }) toggleInputError(checkboxElement) } }) inputList.forEach((inputElement) => { inputElement.addEventListener('input', () => { checkInputValidity(inputElement) toggleButton() }) inputElement.addEventListener('blur', () => { toggleInputError(inputElement) }) inputElement.addEventListener('focus', () => { toggleErrorSpan(inputElement) }) }) checkboxElement.addEventListener('change', () => { toggleInputError(checkboxElement) toggleButton() })}
function startValidation() {
form.addEventListener('submit', (event) => {
event.preventDefault()
if (hasInvalidInput()) {
formError()
inputList.forEach((inputElement) => {
checkInputValidity(inputElement)
toggleInputError(inputElement)
})
toggleInputError(checkboxElement)
}
})
inputList.forEach((inputElement) => {
inputElement.addEventListener('input', () => {
checkInputValidity(inputElement)
toggleButton()
})
inputElement.addEventListener('blur', () => {
toggleInputError(inputElement)
})
inputElement.addEventListener('focus', () => {
toggleErrorSpan(inputElement)
})
})
checkboxElement.addEventListener('change', () => {
toggleInputError(checkboxElement)
toggleButton()
})
}
Функция check использует JavaScript-объект Validity для проверки каждого поля ввода. Если поле не валидно, показывается сообщение об ошибке.
Объект validity можно увидеть, если обратиться к ключу validity элемента input (input). Он выглядит вот так:
{ badInput: false, customError: false, patternMismatch: false, rangeOverflow: false, rangeUnderflow: false, stepMismatch: false, tooLong: false, tooShort: false, typeMismatch: false, valid: true, valueMissing: false,}
{
badInput: false,
customError: false,
patternMismatch: false,
rangeOverflow: false,
rangeUnderflow: false,
stepMismatch: false,
tooLong: false,
tooShort: false,
typeMismatch: false,
valid: true,
valueMissing: false,
}
Чтобы поле ввода считалось валидным, его свойство input должно быть равно true. Это свойство становится true, когда все остальные свойства в объекте validity равны false. Подробнее о validity и значении каждого ключа в этом объекте можно узнать здесь: MDN Web Docs — ValidityState.
В функции check как раз используется объект validity и его ключи pattern для кастомных ошибок и valid для стандартной проверки.
Сначала проверяется задан ли для поля ввода определённый паттерн и установлена ли минимальная длина. Если паттерн задан и не совпадает с введёнными данными, то с помощью функции set передаётся кастомное сообщение об ошибке, хранящееся в атрибуте data. В случае соответствия введённых данных паттерну, с помощью функции check также проверяется длина введённых данных, очищенная от пробелов. Если сообщение больше установленного количества символов и не пустое, то сообщение об ошибке не передаётся, в ином случае — пользователь получает сообщение с минимально необходимым количеством символов.
В функции toggle реализована стандартная проверка: если свойство input равно false, выводится сообщение об ошибке, а если true — ошибка убирается.
function checkInputValidity(inputElement) { if (inputElement.validity.patternMismatch) { inputElement.setCustomValidity(inputElement.dataset.errorMessage) } else { inputElement.setCustomValidity(checkLengthMismatch(inputElement)) }}function checkLengthMismatch(inputElement) { if (inputElement.type !== 'text') { return '' } const valueLength = inputElement.value.trim().length if (valueLength < inputElement.minLength) { return `Минимальное количество символов: ${inputElement.minLength}` } return ''}function toggleInputError(inputElement) { if (!inputElement.validity.valid) { toggleErrorSpan(inputElement, inputElement.validationMessage) } else { toggleErrorSpan(inputElement) }}
function checkInputValidity(inputElement) {
if (inputElement.validity.patternMismatch) {
inputElement.setCustomValidity(inputElement.dataset.errorMessage)
} else {
inputElement.setCustomValidity(checkLengthMismatch(inputElement))
}
}
function checkLengthMismatch(inputElement) {
if (inputElement.type !== 'text') {
return ''
}
const valueLength = inputElement.value.trim().length
if (valueLength < inputElement.minLength) {
return `Минимальное количество символов: ${inputElement.minLength}`
}
return ''
}
function toggleInputError(inputElement) {
if (!inputElement.validity.valid) {
toggleErrorSpan(inputElement, inputElement.validationMessage)
} else {
toggleErrorSpan(inputElement)
}
}
Функция toggle устроена просто: она блокирует кнопку, когда находит невалидные поля, и вновь активирует её, если все поля заполнены корректно. Функция has проверяет поля ввода и чекбокс на наличие ошибок и возвращает true или false, основываясь на том, обнаружены ли невалидные данные.
Блокировка кнопки отправки формы — рискованный приём. Важно учитывать различные варианты поведения пользователя. Чтобы избежать ситуаций, когда пользователь не понимает причину блокировки кнопки, мы принимаем следующие меры:
- Применяем класс
button, который изменяет цвет кнопки на менее яркий, подсказывая пользователю, что нажатие невозможно.- inactive - Добавляем через этот класс свойства
cursor, которое меняет форму курсора на символ запрета.: not - allowed; - При клике по кнопке отправки формы или при нажатии на неё с клавиатуры показываем ошибку, которая объясняет причину блокировки. Реализуем это с помощью JavaScript.
- В случае ввода невалидных данных в одно из полей, пользователь получает обратную связь о допущенной ошибке после потери фокуса на поле или после того, как снят маркер с обязательного чекбокса.
- Как только пользователь ввёл валидные данные, кнопка становится активной.
- Чтобы заблокированная кнопка была заметна пользователям, перемещающимся по сайту с помощью клавиши Tab, мы добавляем к кнопке атрибут
aria.- disabled
Так же напоминаем, что при блокировке кнопки отправки формы важно удостовериться, что требования к заполнению формы разумны и могут быть выполнены всеми пользователями. Следует избегать установления чрезмерно строгих условий для данных, вводимых пользователем. К примеру, пользователь может столкнуться с тем, что его имя слишком длинное для установленного в форме ограничения в 10 символов, что сделает невозможным отправку формы и ограничит доступ к вашему продукту.
function toggleButton() { if (hasInvalidInput()) { buttonElement.classList.add('button-inactive') buttonElement.setAttribute('aria-disabled', 'true') } else { buttonElement.classList.remove('button-inactive') buttonElement.setAttribute('aria-disabled', 'false') formErrorElement.textContent = '' }}function hasInvalidInput() { return ( inputList.some(inputElement => !inputElement.validity.valid) || !checkboxElement.validity.valid )}function formError() { const errorMessage = 'Заполните все поля для отправки формы.' formErrorElement.textContent = errorMessage}
function toggleButton() {
if (hasInvalidInput()) {
buttonElement.classList.add('button-inactive')
buttonElement.setAttribute('aria-disabled', 'true')
} else {
buttonElement.classList.remove('button-inactive')
buttonElement.setAttribute('aria-disabled', 'false')
formErrorElement.textContent = ''
}
}
function hasInvalidInput() {
return (
inputList.some(inputElement => !inputElement.validity.valid) || !checkboxElement.validity.valid
)
}
function formError() {
const errorMessage = 'Заполните все поля для отправки формы.'
formErrorElement.textContent = errorMessage
}
.button-inactive { cursor: not-allowed; background-color: rgb(211 211 211 / 0.6);}.button-inactive:hover { background-color: rgb(211 211 211 / 0.2); border: 2px solid transparent;}.form__empty-error { padding: 10px 0; font-size: 18px; color: #FF8630;}
.button-inactive {
cursor: not-allowed;
background-color: rgb(211 211 211 / 0.6);
}
.button-inactive:hover {
background-color: rgb(211 211 211 / 0.2);
border: 2px solid transparent;
}
.form__empty-error {
padding: 10px 0;
font-size: 18px;
color: #FF8630;
}
Осталось самое лёгкое — сделать активными элементы с ошибками. Если поле ввода оказалось невалидным, то скрипт показывает заранее подготовленный элемент с сообщением об ошибке. Если поле становится валидным, то сообщение исчезает. Именно в этой функции нам пригодился трюк, где мы создавали класс ошибки по следующему шаблону: id input
function toggleErrorSpan(inputElement, errorMessage){ const errorElement = document.querySelector(`.${inputElement.id}-error`) if (errorMessage) { inputElement.classList.add('form__type-input-error') errorElement.textContent = errorMessage errorElement.classList.add('form__error-active') } else { inputElement.classList.remove('form__type-input-error') errorElement.textContent = '' errorElement.classList.remove('form__error-active') }}
function toggleErrorSpan(inputElement, errorMessage){
const errorElement = document.querySelector(`.${inputElement.id}-error`)
if (errorMessage) {
inputElement.classList.add('form__type-input-error')
errorElement.textContent = errorMessage
errorElement.classList.add('form__error-active')
} else {
inputElement.classList.remove('form__type-input-error')
errorElement.textContent = ''
errorElement.classList.remove('form__error-active')
}
}
Также позаботимся об ошибке про пустую форму при клике или нажатии с клавиатуры на кнопку.
const formErrorElement = form.querySelector('.form__empty-error')function startValidation() { form.addEventListener('submit', (event) => { event.preventDefault() // Показываем ошибку if (hasInvalidInput()) { formError() inputList.forEach((inputElement) => { checkInputValidity(inputElement) toggleInputError(inputElement) }) toggleInputError(checkboxElement) } }) inputList.forEach((inputElement) => { inputElement.addEventListener('input', () => { checkInputValidity(inputElement) toggleButton() }) inputElement.addEventListener('blur', () => { toggleInputError(inputElement) }) inputElement.addEventListener('focus', () => { toggleErrorSpan(inputElement) }) }) checkboxElement.addEventListener('change', () => { toggleInputError(checkboxElement) toggleButton() })}function toggleButton() { if (hasInvalidInput()) { buttonElement.classList.add('button-inactive') buttonElement.setAttribute('aria-disabled', 'true') } else { buttonElement.classList.remove('button-inactive') buttonElement.setAttribute('aria-disabled', 'false') // Удаляем текст ошибки formErrorElement.textContent = '' }}// Здесь храним и добавляем текст к нужному контейнеруfunction formError() { const errorMessage = 'Заполните все поля для отправки формы.' formErrorElement.textContent = errorMessage}
const formErrorElement = form.querySelector('.form__empty-error')
function startValidation() {
form.addEventListener('submit', (event) => {
event.preventDefault()
// Показываем ошибку
if (hasInvalidInput()) {
formError()
inputList.forEach((inputElement) => {
checkInputValidity(inputElement)
toggleInputError(inputElement)
})
toggleInputError(checkboxElement)
}
})
inputList.forEach((inputElement) => {
inputElement.addEventListener('input', () => {
checkInputValidity(inputElement)
toggleButton()
})
inputElement.addEventListener('blur', () => {
toggleInputError(inputElement)
})
inputElement.addEventListener('focus', () => {
toggleErrorSpan(inputElement)
})
})
checkboxElement.addEventListener('change', () => {
toggleInputError(checkboxElement)
toggleButton()
})
}
function toggleButton() {
if (hasInvalidInput()) {
buttonElement.classList.add('button-inactive')
buttonElement.setAttribute('aria-disabled', 'true')
} else {
buttonElement.classList.remove('button-inactive')
buttonElement.setAttribute('aria-disabled', 'false')
// Удаляем текст ошибки
formErrorElement.textContent = ''
}
}
// Здесь храним и добавляем текст к нужному контейнеру
function formError() {
const errorMessage = 'Заполните все поля для отправки формы.'
formErrorElement.textContent = errorMessage
}
Наш код готов! Не забудьте:
- Добавить в самое начало функции
startфункциюValidation ( ) toggle, чтобы ещё до ввода символов кнопка была заблокирована.Button ( ) - Вызвать функцию
start.Validation ( )
// Вызываем функциюstartValidation()function startValidation() { toggleButton() form.addEventListener('submit', (event) => { event.preventDefault() if (hasInvalidInput()) { formError() inputList.forEach((inputElement) => { checkInputValidity(inputElement) toggleInputError(inputElement) }) toggleInputError(checkboxElement) } }) inputList.forEach((inputElement) => { inputElement.addEventListener('input', () => { checkInputValidity(inputElement) toggleButton() }) inputElement.addEventListener('blur', () => { toggleInputError(inputElement) }) inputElement.addEventListener('focus', () => { toggleErrorSpan(inputElement) }) }) checkboxElement.addEventListener('change', () => { toggleInputError(checkboxElement) toggleButton() })}
// Вызываем функцию
startValidation()
function startValidation() {
toggleButton()
form.addEventListener('submit', (event) => {
event.preventDefault()
if (hasInvalidInput()) {
formError()
inputList.forEach((inputElement) => {
checkInputValidity(inputElement)
toggleInputError(inputElement)
})
toggleInputError(checkboxElement)
}
})
inputList.forEach((inputElement) => {
inputElement.addEventListener('input', () => {
checkInputValidity(inputElement)
toggleButton()
})
inputElement.addEventListener('blur', () => {
toggleInputError(inputElement)
})
inputElement.addEventListener('focus', () => {
toggleErrorSpan(inputElement)
})
})
checkboxElement.addEventListener('change', () => {
toggleInputError(checkboxElement)
toggleButton()
})
}