JavaScript Form submit() и события форм
Как работают событие submit, form.submit() и form.requestSubmit() в JavaScript: валидация, preventDefault(), кнопка submitter и чтение данных формы.
Обработка отправки форм — одна из наиболее распространённых задач во фронтенд-JavaScript. Формы — это способ, которым пользователи передают данные на сервер: вход в систему, регистрация, поиск, оформление заказа. Почти всегда нужна возможность проверить, преобразовать или подтвердить эти данные до того, как они покинут страницу.
Для этого существуют два связанных, но различных инструмента:
- Событие
submit— генерируется браузером, когда пользователь пытается отправить форму (нажимая кнопку отправки или клавишу Enter в поле ввода). Здесь выполняется валидация и принимается решение — разрешить или отменить отправку. - Метод
form.submit()— отправляет форму программно из кода, без каких-либо действий пользователя.
Важный нюанс, который часто сбивает с толку разработчиков: эти два инструмента несимметричны. Вызов form.submit() не генерирует событие submit и полностью пропускает проверку ограничений. Ниже рассмотрим причины этого и чем лучше воспользоваться вместо него.
Понимание события submit
Событие submit генерируется, когда форма собирается отправить данные. Важно, что оно можно отменить: вызов event.preventDefault() внутри обработчика останавливает переход браузера на другую страницу — это позволяет оставить пользователя на текущей странице для проверки ввода, отображения ошибок или отправки данных через fetch.
Событие генерируется когда:
- Пользователь нажимает
<button type="submit">или<input type="submit">внутри формы. - Пользователь нажимает Enter, находясь в текстовом поле формы, у которой есть кнопка отправки.
Оно не генерируется при вызове form.submit() из JavaScript (см. ниже).
Пример: валидация формы перед отправкой
Этот скрипт предотвращает отправку формы, если поля заполнены некорректно, и показывает пользователю сообщение об ошибке. Он использует встроенную браузерную проверку ограничений (атрибут required и type="email") через checkValidity().
<div>
<form style="display: flex; justify-content: center; gap: 2px; align-items: center; flex-direction: column;" id="registrationForm">
Username: <input type="text" name="username" required />
Email: <input type="email" name="email" required />
<button type="submit">Register</button>
</form>
<div id="message" style="margin-top: 10px; text-align:center;"></div> <!-- Message container for feedback -->
<script>
const form = document.getElementById('registrationForm');
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent actual form submission to a server
const messageDiv = document.getElementById('message');
if (!this.checkValidity()) {
messageDiv.textContent = 'Please fill all required fields correctly.';
messageDiv.style.color = 'red'; // Display the message in red for errors
} else {
messageDiv.textContent = 'The form was successfully submitted.';
messageDiv.style.color = 'green'; // Display the message in green for success
form.reset(); // Reset the form fields after successful submission
}
});
</script>
</div>Функциональность JavaScript:
- Обработчик события: к форме прикреплён обработчик события, который срабатывает при попытке её отправки.
- Проверка валидации: здесь используется функция
checkValidity(). Это встроенный метод HTML-формы, который проверяет все поля на соответствие правилам валидации (например, атрибутrequiredв данном случае). Если хотя бы одно поле не соответствует правилу, функция возвращает false. - Предотвращение отправки: если
checkValidity()возвращает false (то есть форма содержит невалидные или незаполненные обязательные поля), скрипт предотвращает отправку формы на сервер. Вместо этого отображается сообщение с просьбой правильно заполнить все обязательные поля. - Обработка отправки: если все поля валидны, форма показывает сообщение об успехе вместо пустой страницы или отправки на сервер. В реальном приложении именно здесь вы бы вызывали
fetch()для отправки данных.
Чтение отправленных данных
Внутри обработчика обычно нужны значения, введённые пользователем. Самый удобный способ — объект FormData, который за один шаг собирает все именованные элементы управления:
const form = document.getElementById("registrationForm");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = Object.fromEntries(new FormData(form));
console.log(data.username, data.email);
// data is a plain object: { username: "...", email: "..." }
});Определение нажатой кнопки
Когда у формы несколько кнопок отправки (например, «Сохранить» и «Удалить»), событие submit сообщает, какая из них вызвала отправку, через event.submitter:
form.addEventListener("submit", (event) => {
event.preventDefault();
// event.submitter is the button element that caused submission
console.log("Submitted via:", event.submitter?.value);
});Использование метода .submit()
Метод .submit() инициирует отправку формы программно — непосредственно из кода, без нажатия кнопки пользователем. Он полезен, когда форму нужно отправить после выполнения определённого условия (таймер, успешная автоматическая проверка, значение, вычисленное в JavaScript).
Два нюанса делают поведение .submit() отличным от пользовательской отправки:
- Он не генерирует событие
submit, поэтому любые валидация или логика, привязанные к этому событию, пропускаются. - Он не запускает проверку ограничений браузера, поэтому правила
requiredиtypeигнорируются.
Это сделано намеренно — исторически .submit() был предназначен для отправки без повторного запуска самого обработчика, вызвавшего его (иначе возникла бы бесконечная рекурсия). В большинстве случаев лучше использовать form.requestSubmit() (рассмотрен ниже), который ведёт себя как настоящая пользовательская отправка.
Пример: программная отправка формы
Пример ниже отправляет форму из кода сразу после загрузки страницы. Поскольку у формы нет атрибута action, данные отправляются на текущую страницу; alert показывает значение скрытого поля, чтобы вы могли видеть, что именно было бы отправлено:
<!DOCTYPE html>
<html>
<head>
<title>Auto Submit Form Demo</title>
</head>
<body>
<form id="autoSubmitForm">
<input type="hidden" name="data" value="Automatic Submission" />
</form>
<script>
function submitFormAutomatically() {
document.getElementById('autoSubmitForm').submit();
alert("Form submitted with data: " + document.getElementById('autoSubmitForm').data.value);
}
document.addEventListener('DOMContentLoaded', submitFormAutomatically); // Call the function when the DOM is ready
</script>
</body>
</html>Обратите внимание: document.getElementById('autoSubmitForm').data работает потому, что именованные элементы управления формы доступны как свойства элемента формы — form.data возвращает элемент <input name="data">, а .value читает его значение.
Предпочитайте requestSubmit() вместо submit()
form.requestSubmit() — современный и более безопасный аналог form.submit(). В отличие от .submit(), он:
- генерирует событие
submit, поэтому обработчики валидации запускаются; - выполняет проверку ограничений браузера и показывает встроенные подсказки об ошибках, если поле невалидно;
- опционально принимает кнопку, чтобы задать
event.submitter, напримерform.requestSubmit(saveButton).
const form = document.getElementById("registrationForm");
// Behaves exactly like a real user click on the submit button:
form.requestSubmit();Если вам действительно нужно обойти обработчики, как при .submit(), но при этом всё же запустить свой обработчик, можно самостоятельно сгенерировать событие: form.dispatchEvent(new Event('submit', { cancelable: true })) — но в большинстве случаев правильным выбором будет requestSubmit().
Совместное использование .submit() с обработчиками событий
Вы также можете обусловить отправку собственными критериями: отправлять форму только при выполнении определённых условий. Пример ниже использует обычную (не submit) кнопку — ничего не происходит, пока JavaScript не решит вызвать submit().
Пример: условная отправка формы
<form id="conditionalForm">
Accept Terms: <input type="checkbox" id="acceptTerms">
<button type="button" onclick="checkAndSubmit()">Submit</button>
</form>
<script>
function checkAndSubmit() {
var form = document.getElementById('conditionalForm');
var termsCheckbox = document.getElementById('acceptTerms');
if (termsCheckbox.checked) {
form.submit();
} else {
alert('You must accept the terms and conditions to proceed.');
}
}
</script>Этот код реализует кнопку, которая при нажатии проверяет, установлен ли флажок, прежде чем отправить форму. Если условия не приняты, пользователь получает оповещение. Обратите внимание: поскольку здесь используется form.submit(), событие submit не будет сгенерировано — замените на form.requestSubmit(), если у вас есть обработчик submit, который должен выполниться.
submit event vs. submit() vs. requestSubmit()
| Поведение | Событие submit | form.submit() | form.requestSubmit() |
|---|---|---|---|
| Инициируется действием пользователя | Да | Нет (только из кода) | Нет (только из кода) |
Генерирует событие submit | — | Нет | Да |
| Выполняет проверку ограничений | н/д | Нет | Да |
Можно отменить (preventDefault) | Да | Нет | Да (через событие) |
Устанавливает event.submitter | Да | Нет | Да (передайте кнопку) |
Практическое правило: слушайте событие submit для валидации и перехвата; вызывайте requestSubmit() для программной инициации отправки; прибегайте к .submit() только тогда, когда намеренно хотите обойти собственные обработчики.
Заключение
Событие submit позволяет перехватить и проверить форму до её отправки, а .submit() и requestSubmit() дают возможность отправить её из кода. Главное, что нужно запомнить: .submit() незаметно пропускает и событие submit, и валидацию — поэтому предпочитайте requestSubmit(), если только не хотите намеренно этого избежать. В сочетании с event.preventDefault() и FormData эти инструменты дают полный контроль над тем, как собираются и отправляются данные пользователя.
Для дальнейшего изучения смотрите свойства и методы форм, API проверки ограничений, события change и input для реакции на изменения в полях, а также focus и blur для взаимодействия на уровне поля.