Перейти к содержимому
FFormhook
Назад к блогу

Блог

AJAX-отправка формы: отправить форму без перезагрузки страницы

· 4 мин чтения

Отправьте HTML-форму обычным способом - и браузер сделает то, что делал всегда: перейдёт на новую страницу или перезагрузит текущую, отбросив всё, что было на экране мгновение назад. Для формы, живущей на собственной странице, это безобидно. Но для формы внутри модального окна, чат-виджета, процесса оформления заказа или любого одностраничного приложения полная навигация - это резкий сброс: модальное окно закрывается, приложение монтируется заново, позиция прокрутки теряется. AJAX-отправка - отправка данных формы через JavaScript-функцию fetch() вместо того, чтобы позволить браузеру перейти на другую страницу - решает эту проблему, и для неё нужно всего несколько строк кода.

Зачем избегать перезагрузки страницы

Полная перезагрузка страницы отбрасывает всё, что JavaScript держал в памяти: открытое модальное окно, текущий шаг мастера, несохранённое состояние в другом месте страницы. Если форма живёт внутри дерева компонентов React, Vue или Svelte, переход браузера на другую страницу также разрушает всё клиентское приложение, которое затем приходится загружать заново с нуля.

Отправка через fetch() сохраняет страницу - и приложение, работающее на ней, - нетронутыми. Вы сами решаете, что произойдёт дальше: показать сообщение об успехе прямо на странице, закрыть модальное окно, сбросить поля, при необходимости перенаправить программно. В этом разница между «браузер решает» и «решаете вы».

Это улучшение, а не требование

Вам не нужно выбирать один из двух подходов. Оставьте атрибуты action и method у тега <form> точно такими же, как для обычного POST-запроса, и перехватывайте событие отправки через JavaScript только когда он доступен. Если скрипт не загрузился, расширение браузера вмешалось, или у посетителя вовсе отключён JavaScript, форма всё равно работает - она просто откатывается к обычной навигации по странице вместо встроенного сообщения о статусе. В этом вся суть прогрессивного улучшения: базовый случай - HTML-форма, отправляющая данные напрямую на https://formhook.app/f/{apiKey}, - всегда работает сама по себе. JavaScript лишь делает это приятнее, когда он есть.

Минимальный пример

Никакого фреймворка не требуется - вот весь паттерн на чистом JavaScript. Он предотвращает переход по умолчанию, отправляет данные формы как FormData и подставляет сообщение о статусе в зависимости от результата:

const form = document.querySelector("#contact-form");
form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const res = await fetch(form.action, {
    method: "POST",
    body: new FormData(form),
    headers: { Accept: "application/json" },
  });
  if (res.ok) {
    form.reset();
    document.querySelector("#form-status").textContent = "Thanks - we got it.";
  } else {
    document.querySelector("#form-status").textContent = "Something went wrong. Please try again.";
  }
});

Запрашивайте JSON, а не редирект

Обратите внимание на заголовок Accept: application/json в примере выше. Без него бэкенд форм, рассчитанный ещё и на обычные HTML-отправки, может попытаться перенаправить браузер на страницу «спасибо» - правильное поведение для обычного POST-запроса, но бесполезное, когда вы вызываете его из fetch(). Отправка Accept: application/json сообщает эндпоинту Formhook, что запрос пришёл из JavaScript, поэтому он возвращает JSON-ответ об успехе или ошибке вместо редиректа, и ваш код может ветвиться по res.ok, как в примере. Точный формат запроса смотрите в документации.

Не забудьте про доступность

Подстановка сообщения о статусе через textContent невидима для программ чтения с экрана, если только вы не попросите браузер объявить её вслух. Добавьте элементу статуса (тому самому, на который указывает document.querySelector("#form-status") в примере) атрибут aria-live="polite", и вспомогательные технологии озвучат обновление в момент его изменения - успех это или ошибка, - без того, чтобы посетителю пришлось самому находить элемент и переводить на него фокус. Это всего один атрибут, и именно он определяет разницу между формой, которая работает для всех, и формой, которая незаметно исключает пользователей экранных дикторов в тот момент, когда управление берёт на себя JavaScript.

Ничего из этого не требует библиотеки или SDK - эндпоинт Formhook принимает обычный POST-запрос формы с любого сайта, а версия с fetch() выше - лишь необязательное прогрессивное улучшение поверх этого, а не обязательное условие. Полный справочник по запросам и ответам смотрите в документации, а лимиты бесплатного тарифа - на странице цен.

Рабочая форма в одну строку

Размещение в ЕС, отправки хранятся вечно, push-уведомления на любом тарифе.

Начать бесплатно

Без банковской карты · читайте документацию

Читать дальше