Отправка форм в JavaScript
Вы уже умеете работать с элементами форм на JavaScript, обрабатывая их в браузере. Формы, однако, можно также отправлять на сервер, чтобы их обработала серверная часть сайта, написанная на PHP или NodeJS.
Это нужно для того, чтобы добавлять и изменять данные сайта, хранящиеся на сервере.
Давайте посмотрим, как это делается. Пусть у нас есть несколько инпутов и кнопка:
Обернем наши элементы в тег form . В этом случае у нас получится форма, которая по нажатию на кнопку будет отправляться на сервер:
Чтобы на сервере можно было получить данные формы, необходимо каждому инпуту дать свое имя:
В этом случае на сервер данные формы придут в виде пар ключ-значение , где ключами будут имена элементов формы, а значениями — введенные данные.
Для того, чтобы отправить форму, нет необходимости в сервере. Вы можете скопировать приведенный код формы в любой файл, запустить его в браузер и нажать на кнопку отправки — форма отправится и страница браузера перезагрузится.
При отсутствии сервера, однако, данные формы никуда не попадут. Поэтому давайте будем проверять работу формы вместе с сервером. Пока вы не знаете никаких серверных языков, поэтому потренируемся отправлять форму с помощью нашего учебного HTTP сервера.
Давайте разместим нашу форму в некотором файле так, чтобы она была доступна по адресу http://localhost:3001/form.html :
Добавим нашей форме атрибут action , указывающий адрес отправки нашей формы:
Теперь в файле server.js напишем обработчик адреса отправки формы:
export default < '/handler/': function() < return 'form data received'; >>
В параметр нашего обработчика попадут отправленные данные формы:
export default < '/handler/': function(data) < console.log(data); // выведется в консоль сервера return 'form data received'; >>
Создайте форму и файл для ее обработки. Отправьте форму и проверьте, что данные действительно пришли на сервер.
FormData
В этой главе речь пойдёт об отправке HTML-форм: с файлами и без, с дополнительными полями и так далее. Объекты FormData помогут нам с этим. Как вы, наверняка, догадались по его названию, это объект, представляющий данные HTML формы.
let formData = new FormData([form]);
Если передать в конструктор элемент HTML-формы form , то создаваемый объект автоматически прочитает из неё поля.
Его особенность заключается в том, что методы для работы с сетью, например fetch , позволяют указать объект FormData в свойстве тела запроса body .
Он будет соответствующим образом закодирован и отправлен с заголовком Content-Type: multipart/form-data .
То есть, для сервера это выглядит как обычная отправка формы.
Отправка простой формы
Давайте сначала отправим простую форму.
Как вы видите, код очень компактный:
В этом примере серверный код не представлен, он за рамками этой статьи, он принимает POST-запрос с данными формы и отвечает сообщением «Пользователь сохранён».
Методы объекта FormData
С помощью указанных ниже методов мы можем изменять поля в объекте FormData :
- formData.append(name, value) – добавляет к объекту поле с именем name и значением value ,
- formData.append(name, blob, fileName) – добавляет поле, как будто в форме имеется элемент , третий аргумент fileName устанавливает имя файла (не имя поля формы), как будто это имя из файловой системы пользователя,
- formData.delete(name) – удаляет поле с заданным именем name ,
- formData.get(name) – получает значение поля с именем name ,
- formData.has(name) – если существует поле с именем name , то возвращает true , иначе false
Технически форма может иметь много полей с одним и тем же именем name , поэтому несколько вызовов append добавят несколько полей с одинаковыми именами.
Ещё существует метод set , его синтаксис такой же, как у append . Разница в том, что .set удаляет все уже имеющиеся поля с именем name и только затем добавляет новое. То есть этот метод гарантирует, что будет существовать только одно поле с именем name , в остальном он аналогичен .append :
- formData.set(name, value) ,
- formData.set(name, blob, fileName) .
Поля объекта formData можно перебирать, используя цикл for..of :
let formData = new FormData(); formData.append('key1', 'value1'); formData.append('key2', 'value2'); // Список пар ключ/значение for(let [name, value] of formData) < alert(`$= $`); // key1=value1, потом key2=value2 >
Отправка формы с файлом
Объекты FormData всегда отсылаются с заголовком Content-Type: multipart/form-data , этот способ кодировки позволяет отсылать файлы. Таким образом, поля тоже отправляются, как это и происходит в случае обычной формы.
Пример такой формы:
Картинка:
Отправка формы с Blob-данными
Ранее в главе Fetch мы видели, что очень легко отправить динамически сгенерированные бинарные данные в формате Blob . Мы можем явно передать её в параметр body запроса fetch .
Но на практике бывает удобнее отправлять изображение не отдельно, а в составе формы, добавив дополнительные поля для имени и другие метаданные.
Кроме того, серверы часто настроены на приём именно форм, а не просто бинарных данных.
В примере ниже посылается изображение из и ещё несколько полей, как форма, используя FormData :
Пожалуйста, обратите внимание на то, как добавляется изображение Blob :
formData.append("image", imageBlob, "image.png");
Это как если бы в форме был элемент и пользователь прикрепил бы файл с именем «image.png» (3-й аргумент) и данными imageBlob (2-й аргумент) из своей файловой системы.
Сервер прочитает и данные и файл, точно так же, как если бы это была обычная отправка формы.
Итого
Объекты FormData используются, чтобы взять данные из HTML-формы и отправить их с помощью fetch или другого метода для работы с сетью.
Мы можем создать такой объект уже с данными, передав в конструктор HTML-форму – new FormData(form) , или же можно создать объект вообще без формы и затем добавить к нему поля с помощью методов:
- formData.append(name, value)
- formData.append(name, blob, fileName)
- formData.set(name, value)
- formData.set(name, blob, fileName)
Отметим две особенности:
- Метод set удаляет предыдущие поля с таким же именем, а append – нет. В этом их единственное отличие.
- Чтобы послать файл, нужно использовать синтаксис с тремя аргументами, в качестве третьего как раз указывается имя файла, которое обычно, при , берётся из файловой системы.
- formData.delete(name)
- formData.get(name)
- formData.has(name)
submit
Событие submit возникает, когда пользователь отправляет валидную форму. Если форма невалидна и её нельзя отправить, то и submit не будет.
Как пишется
Скопировать ссылку «Как пишется» Скопировано
На submit можно подписаться и отреагировать, например, сказать спасибо:
document.addEventListener('submit', function () alert('Спасибо, что заполнили форму!')>)document.addEventListener('submit', function () alert('Спасибо, что заполнили форму!') >)
Как понять
Скопировать ссылку «Как понять» Скопировано
Пользователь может отправить форму (и создать для нас событие submit ) разными способами. Например, нажать клавишу Enter внутри поля или кликнуть по кнопке .
Если мы вытащим, например, кнопку из формы, то событие submit при клике на кнопку уже не произойдёт, потому что связи с формой больше нет. В то же время, нажатие Enter внутри поля будет работать.
div> form> label for="input-field">Нажмите Enter в поле:label> input id="input-field" type="text"> form> div> div> button>Или кликните тутbutton> div>
document.addEventListener('submit', function () alert('Случился submit')>)document.addEventListener('submit', function () alert('Случился submit') >)
На практике
Скопировать ссылку «На практике» Скопировано
Алексей Никитченко советует
Скопировать ссылку «Алексей Никитченко советует» Скопировано
За отправкой формы лучше всегда наблюдать через подписку именно на событие submit .
Это удобнее и правильнее, ведь submit связан сразу с каждым элементом формы, а пользователь может отправить её разными способами. Например, нажать на клавишу Enter в поле ввода и не трогать вовсе красивую кнопку подтверждения. В то же время подписка на другие события, например на click по кнопке, будет лишь косвенно связано с отправкой формы.
В примере ниже подпишемся на событие click по кнопке формы и выведем сообщение с названием элемента, на котором сработает click . Попробуйте нажать Enter внутри поля ввода ⌨️.
const button = document.getElementById('submit-button') button.addEventListener('click', function (event) alert(`Событие поймано на $`)>)const button = document.getElementById('submit-button') button.addEventListener('click', function (event) alert(`Событие поймано на $event.currentTarget>`) >)
Хотя мы не трогаем кнопку, событие click на ней всё равно возникает. При отправке формы браузер «синтетически» кликает по кнопке на случай, если какое-то действие привязано к ней, а не к submit . Но выходит мы работаем с одним элементом, а событие возникает на другом.
Иначе с submit — мы точно работаем с формой в целом вместо отдельных элементов и улучшаем доступность для пользователей без мыши.
как отправить форму js
Чтобы отправить форму с помощью JavaScript, нужно использовать метод submit() для формы. Это можно сделать так:
const myForm = document.getElementById('myForm'); // получаем форму по ее id myForm.submit(); // отправляем форму
В этом примере мы получаем форму по ее идентификатору myForm с помощью метода getElementById() , а затем вызываем метод submit() , который отправляет форму.
Кроме того, вы можете добавить обработчик событий на отправку формы, чтобы выполнить некоторый код, когда форма отправляется. Например:
const myForm = document.getElementById('myForm'); myForm.addEventListener('submit', function (event) // Отменяем стандартное поведение формы event.preventDefault(); // Получаем данные из формы const formData = new FormData(myForm); // Отправляем данные на сервер fetch('/api/submit-form', method: 'POST', body: formData, >) .then((response) => // Обрабатываем ответ от сервера console.log(response); >) .catch((error) => // Обрабатываем ошибку console.error(error); >); >);
В этом примере мы добавляем обработчик событий на отправку формы, который отменяет стандартное поведение формы с помощью метода preventDefault() . Затем мы получаем данные из формы с помощью объекта FormData , создаем запрос POST с помощью fetch() и отправляем данные на сервер. В конце мы обрабатываем ответ от сервера или ошибку с помощью методов then() и catch() .