Работа с FormData

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

Создание и инициализация FormData

FormData создаётся на основе элемента <form> или как пустой объект, в который можно добавлять пары ключ-значение:

import { define, Component, h } from 'skatejs';

class MyForm extends Component {
  static get is() { return 'my-form'; }

  renderCallback() {
    return (
      <form id="userForm">
        <input name="username" type="text" />
        <input name="email" type="email" />
        <button type="submit">Отправить</button>
      </form>
    );
  }

  connectedCallback() {
    super.connectedCallback();
    const form = this.querySelector('#userForm');
    form.addEventListener('submit', this.handleSubmit.bind(this));
  }

  handleSubmit(event) {
    event.preventDefault();
    const form = event.target;
    const formData = new FormData(form);
    console.log('Данные формы:', Object.fromEntries(formData.entries()));
  }
}

define(MyForm);

Ключевые моменты:

  • new FormData(form) автоматически собирает все поля формы, включая <input>, <select> и <textarea>.
  • formData.entries() возвращает итератор для всех пар «ключ-значение».
  • Object.fromEntries() позволяет преобразовать данные в обычный объект для удобной работы.

Добавление и удаление данных вручную

FormData можно использовать не только с формой, но и для динамически создаваемых данных:

const formData = new FormData();
formData.append('username', 'ivan');
formData.append('email', 'ivan@example.com');
formData.append('file', fileInput.files[0]);

formData.delete('email');

Особенности:

  • append(key, value) добавляет новое значение. Если ключ уже существует, создается массив значений.
  • delete(key) полностью удаляет указанный ключ.
  • set(key, value) заменяет текущее значение ключа, если оно существует, или создаёт новый.

Отправка данных на сервер

Использование fetch с FormData позволяет отправлять данные без ручного кодирования:

handleSubmit(event) {
  event.preventDefault();
  const form = event.target;
  const formData = new FormData(form);

  fetch('/api/submit', {
    method: 'POST',
    body: formData,
  })
    .then(response => response.json())
    .then(data => console.log('Ответ сервера:', data))
    .catch(err => console.error('Ошибка:', err));
}

Важные моменты:

  • Нет необходимости устанавливать заголовок Content-Type, браузер автоматически устанавливает multipart/form-data.
  • Поддерживаются файлы, изображения и бинарные данные.
  • Сервер может получать данные как обычные поля формы.

Динамическое добавление форм и полей

В SkateJS компоненты можно строить динамически. FormData легко интегрируется с динамическими элементами:

addInputField(name, value) {
  const form = this.querySelector('#userForm');
  const input = document.createElement('input');
  input.name = name;
  input.value = value;
  form.appendChild(input);
}

После добавления нового поля вызов new FormData(form) автоматически включит его в отправку.

Чтение данных без отправки

FormData позволяет извлекать данные без необходимости отправки формы на сервер:

const form = this.querySelector('#userForm');
const formData = new FormData(form);

for (let [key, value] of formData.entries()) {
  console.log(`${key}: ${value}`);
}

Методы get(key) и getAll(key) позволяют получать отдельные значения:

const username = formData.get('username');
const emails = formData.getAll('email'); // если несколько полей с одинаковым именем

Интеграция с SkateJS и реактивными свойствами

SkateJS позволяет создавать реактивные свойства, которые можно связывать с формой:

static get props() {
  return {
    username: String,
    email: String
  };
}

handleInput(event) {
  this[event.target.name] = event.target.value;
}

renderCallback() {
  return (
    <form id="userForm" onIn put={this.handleInput.bind(this)}>
      <input name="username" type="text" value={this.username} />
      <input name="email" type="email" value={this.email} />
    </form>
  );
}

Преимущества такого подхода:

  • Данные формы синхронизированы с состоянием компонента.
  • Можно легко отправлять FormData, собирая значения из реактивных свойств, если форма динамическая.
  • Упрощается интеграция с API.

Обработка файлов в формах

FormData особенно удобен для работы с файлами:

const fileInput = this.querySelector('input[type="file"]');
const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('/upload', { method: 'POST', body: formData });
  • Можно добавлять несколько файлов через append('files[]', file).
  • FormData сохраняет исходный тип файлов и имена, что упрощает обработку на сервере.

Советы по производительности

  • Не создавать новый объект FormData для каждого поля; лучше собирать все данные сразу.
  • Для больших форм избегать избыточных вызовов entries().
  • Использовать реактивные свойства компонента для отслеживания изменений в полях формы, чтобы уменьшить количество операций с DOM.

FormData в SkateJS становится мощным инструментом для создания интерактивных форм, позволяя легко интегрировать динамические элементы, файлы и синхронизацию с внутренним состоянием компонентов.