JavaScript FormData
JavaScript FormData API: создание объектов FormData, чтение и изменение полей с get, append, set и delete, отправка данных и файлов через fetch.
Эффективная работа с данными форм — необходимое условие создания динамичных, интерактивных веб-страниц. Именно для этого JavaScript предоставляет FormData API: он позволяет собирать поля формы, программно формировать наборы пар «ключ/значение» и отправлять их на сервер — в том числе с файлами. В этом руководстве рассматривается, что такое FormData, как создавать и читать его, все доступные методы, отправка через fetch и типичные ошибки.
Знакомство с FormData
FormData — это встроенный object JavaScript, представляющий набор пар «ключ/значение», смоделированный по образцу того, как браузер отправляет HTML-форму. Он упрощает сбор данных из HTML-форм и их асинхронную отправку на сервер с помощью Fetch API.
Почему стоит использовать его вместо обычного object?
- Он автоматически считывает существующие поля формы — не нужно вручную извлекать
valueиз каждого поля ввода. - Он поддерживает файлы и
Blob-объекты, которые обычные object и JSON передавать не могут. - При передаче в
fetchбраузер автоматически устанавливает правильныйContent-Type(multipart/form-data) с нужным разделителем (boundary).
Создание объектов FormData
Создайте объект FormData с помощью конструктора FormData(). Если передать элемент <form>, все именованные, активные поля этой формы будут захвачены автоматически. Содержимое можно просмотреть, перебирая метод entries(), который возвращает итератор пар [key, value]:
<script>
function onSubmit(event) {
event.preventDefault();
const form = document.getElementById('myForm');
const formData = new FormData(form);
let results = '';
for (const [key, value] of formData.entries()) {
results += `${key}: ${value}\n`;
}
alert(results)
}
</script>
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="username" value="John Doe" />
<input type="email" name="email" value="[email protected]" />
<input type="submit" />
</form>Доступ к данным формы
Прочитайте одно поле с помощью get() или переберите все поля через entries(), как показано выше. get() возвращает первое значение для ключа (или null, если его не существует):
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="username" value="John Doe" />
<input type="email" name="email" value="[email protected]" />
<input type="submit" />
</form>
<script>
function onSubmit(event) {
const form = document.getElementById('myForm');
const formData = new FormData(form);
const username = formData.get('username');
const email = formData.get('email');
alert(`username: ${username}; email: ${email}`);
}
</script>Методы FormData
Помимо чтения существующей формы, FormData позволяет вручную формировать и изменять набор данных. На каждом экземпляре доступны следующие методы:
| Метод | Что делает |
|---|---|
append(name, value) | Добавляет новое значение. Если ключ уже существует, сохраняет старое значение и добавляет ещё одно — ключ может иметь несколько значений. |
set(name, value) | Устанавливает значение для ключа, заменяя все существующие значения этого ключа. |
get(name) | Возвращает первое значение для ключа или null. |
getAll(name) | Возвращает array всех значений для ключа. |
has(name) | Возвращает true, если ключ существует. |
delete(name) | Удаляет все значения для ключа. |
entries() / keys() / values() | Итераторы по парам, ключам или значениям. |
Разница между append и set — наиболее частый источник ошибок:
const fd = new FormData();
fd.append('tag', 'js');
fd.append('tag', 'web'); // append keeps both
console.log(fd.getAll('tag')); // [ 'js', 'web' ]
fd.set('tag', 'html'); // set replaces all
console.log(fd.getAll('tag')); // [ 'html' ]
console.log(fd.has('tag')); // true
fd.delete('tag');
console.log(fd.has('tag')); // falseМожно также создать FormData полностью в коде — без какой-либо формы — добавляя поля напрямую. Третий аргумент append/set задаёт имя файла, когда значением является Blob или File.
Отправка FormData через Fetch API
Распространённый сценарий использования FormData — асинхронная отправка данных формы на сервер. Передайте экземпляр FormData в качестве body запроса fetch — браузер автоматически установит Content-Type в multipart/form-data с правильным разделителем, поэтому не нужно устанавливать этот заголовок вручную:
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="title" value="A title" />
<input type="text" name="body" value="A body" />
<input type="submit" value="Submit Post" />
</form>
<div>post id: <span id="response"></span></div>
<script>
function onSubmit(event) {
event.preventDefault();
const form = document.getElementById('myForm');
const formData = new FormData(form);
const responseSpan = document.getElementById('response');
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => { responseSpan.innerHTML = data.id; })
.catch(error => console.error('Error:', error));
}
</script>При передаче формы в конструктор FormData он автоматически включает все поля HTML-формы, в том числе скрытые. Это может привести к непредвиденному поведению, если вы не будете осторожны, особенно при наличии в форме конфиденциальных или лишних полей.
Загрузка файлов
FormData — стандартный способ загрузки файлов, поскольку он формирует запрос multipart/form-data, способный передавать двоичное содержимое вместе с текстовыми полями. При создании FormData из формы, содержащей <input type="file"> input, выбранный файл уже включён — не нужно читать input.files и добавлять его повторно:
<form id="fileUploadForm">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
<script>
const form = document.getElementById('fileUploadForm');
form.addEventListener('submit', (event) => {
event.preventDefault();
// The file input is captured automatically from the form.
const formData = new FormData(form);
fetch('https://httpbin.org/post', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log('Upload successful:', data))
.catch(error => console.error('Error:', error));
});
</script>Чтобы прикрепить файл, не являющийся частью формы — например, выбранный программно, — добавьте его явно, при необходимости указав имя файла:
const formData = new FormData();
formData.append('avatar', fileObject, 'profile.png');FormData и URLSearchParams
Оба объекта оборачивают пары «ключ/значение», но сериализуются по-разному. Используйте FormData, когда нужно отправить файлы или тело multipart/form-data. Используйте URLSearchParams, когда у вас только текст и нужно компактное тело application/x-www-form-urlencoded (или строка запроса). Можно даже создать один из другого, если все значения являются string:
const fd = new FormData();
fd.append('q', 'cats');
fd.append('page', '2');
const params = new URLSearchParams(fd);
console.log(params.toString()); // q=cats&page=2Заключение
FormData — универсальный и мощный инструмент для управления данными форм в JavaScript-приложениях. Будь то простые текстовые поля или сложная загрузка файлов, FormData упрощает этот процесс и предоставляет удобный интерфейс для работы с данными форм. Освоив FormData, вы сможете повысить интерактивность и отзывчивость своих веб-приложений, обеспечив пользователям бесперебойный опыт взаимодействия.