Atomico — библиотека для создания веб-компонентов с реактивным подходом, и работа с формами занимает важное место в её экосистеме. Одной из ключевых задач является сбор данных формы и их отправка на сервер. Для этого используется объект FormData, который предоставляет удобный интерфейс для работы с парами «ключ-значение» из HTML-форм.
FormData создаётся на основе HTML-формы или как пустой объект:
const form = document.querySelector('form');
const data = new FormData(form); // Автоматически собирает все input, select, textarea
Можно создавать пустой объект и добавлять пары вручную:
const data = new FormData();
data.append('username', 'ivan');
data.append('password', '12345');
Особенности FormData:
multipart/form-data.append.В Atomico формы обычно обрабатываются через обработчики событий, подключенные к элементам формы. Пример компонента:
import { c, useEffect } from "atomico";
function loginForm() {
const handleSubmit = (event) => {
event.preventDefault();
const form = event.target;
const data = new FormData(form);
sendData(data);
};
return (
<host>
<form onSub mit={handleSubmit}>
<input name="username" type="text" required />
<input name="password" type="password" required />
<button type="submit">Войти</button>
</form>
</host>
);
}
loginForm.props = {};
export const LoginForm = c(loginForm);
Здесь event.preventDefault() предотвращает стандартное
поведение формы, а FormData собирает все значения элементов с атрибутом
name.
Для отправки данных удобно использовать fetch. FormData
передаётся напрямую в тело запроса:
async function sendData(formData) {
try {
const response = await fetch('/api/login', {
method: 'POST',
body: formData
});
const result = await response.json();
console.log(result);
} catch (error) {
console.error('Ошибка отправки формы', error);
}
}
Особенности работы с fetch и FormData:
Content-Type не нужно указывать вручную —
браузер автоматически устанавливает multipart/form-data с
boundary.FormData для
отправки JSON, но в этом случае данные сначала нужно сериализовать, что
делает FormData менее необходимым.FormData особенно удобна для загрузки файлов. Пример компонента с загрузкой изображения:
function uploadForm() {
const handleUpload = (event) => {
event.preventDefault();
const form = event.target;
const data = new FormData(form);
fetch('/api/upload', {
method: 'POST',
body: data
})
.then(res => res.json())
.then(console.log)
.catch(console.error);
};
return (
<host>
<form onSub mit={handleUpload}>
<input type="file" name="avatar" />
<button type="submit">Загрузить</button>
</form>
</host>
);
}
export const UploadForm = c(uploadForm);
Особенности:
<input type="file" name="files" multiple />.FormData предоставляет методы set, get,
delete, has, что позволяет динамически
изменять данные перед отправкой:
const data = new FormData();
data.append('username', 'ivan');
data.set('username', 'petr'); // заменяет значение
data.has('username'); // true
data.delete('username'); // удаляет ключ
Это полезно для добавления скрытых полей, токенов авторизации или других параметров на этапе отправки.
В Atomico можно использовать useState для отслеживания
состояния формы и динамического обновления FormData:
import { c, useState } from "atomico";
function reactiveForm() {
const [formData, setFormData] = useState(new FormData());
const handleChange = (event) => {
const { name, value } = event.target;
formData.set(name, value);
setFormData(formData);
};
const handleSubmit = (event) => {
event.preventDefault();
fetch('/api/submit', { method: 'POST', body: formData });
};
return (
<host>
<form onSub mit={handleSubmit}>
<input name="firstName" onIn put={handleChange} />
<input name="lastName" onIn put={handleChange} />
<button type="submit">Отправить</button>
</form>
</host>
);
}
export const ReactiveForm = c(reactiveForm);
Такой подход позволяет динамически формировать данные на лету, без необходимости заново создавать объект FormData на каждом сабмите.
FormData напрямую при работе с файлами, а
для простых текстовых данных может быть удобнее JSON.FormData в сочетании с Atomico позволяет создавать реактивные и динамические формы, легко интегрируемые с серверной частью, с минимальной нагрузкой на код и максимально чистым интерфейсом.