Отправка форм

Отправка данных формы с интегрированным компонентом Tom Select требует понимания того, как библиотека преобразует выбранные элементы в значение input-поля, каким образом эти значения сериализуются браузером и как они интерпретируются на серверной стороне. В стандартной конфигурации Tom Select заменяет обычный <select> на управляемый JavaScript-интерфейс, при этом сохраняя связь с оригинальным элементом формы через синхронизацию значений.

В основе поведения лежит принцип: значения, выбранные в интерфейсе Tom Select, отражаются в исходном DOM-элементе <select> или скрытом <input>. При отправке формы браузер собирает данные исключительно из DOM, а не из внутреннего состояния JavaScript-компонента.

Для случая <select multiple> формируется массив значений:

<form id="userForm">
  <select id="tags" name="tags[]" multiple>
    <option value="js">JavaScript</option>
    <option value="ts">TypeScript</option>
    <option value="css">CSS</option>
  </select>

  <button type="submit">Отправить</button>
</form>

Инициализация Tom Select:

new TomSelect("#tags", {
  plugins: ["remove_button"]
});

После выбора нескольких значений DOM-структура <select> содержит отмеченные <option selected>, что и становится источником данных при submit.


Формирование данных при стандартной отправке

При классической отправке формы (application/x-www-form-urlencoded) браузер сериализует выбранные значения следующим образом:

tags[]=js&tags[]=css

Если используется одиночный select без multiple, передается одно значение:

tags=js

Tom Select не изменяет механизм сериализации формы, что делает его совместимым с серверными фреймворками, ожидающими стандартные формы HTML.


Использование режима создания элементов (create:true)

При включенной опции создания новых элементов:

new TomSelect("#tags", {
  create: true
});

пользовательские значения не присутствуют в исходном списке <option>. Tom Select динамически добавляет их в DOM:

<option value="new-value" selected>new-value</option>

Таким образом, даже пользовательские значения становятся частью стандартной HTML-сериализации.

Особенность этого режима заключается в том, что сервер не различает заранее определённые и пользовательские значения без дополнительной логики.


Скрытые input и альтернативная модель хранения

В ряде конфигураций используется скрытый <input> вместо <select>. Это характерно для сценариев, где требуется отправка JSON или кастомного формата.

<form id="form">
  <input id="tagsInput" name="tags" type="hidden">
</form>

Инициализация:

new TomSelect("#tagsInput", {
  persist: false,
  create: true,
  onChange: function(values) {
    this.input.value = JSON.stringify(values);
  }
});

В данном случае Tom Select полностью контролирует сериализацию, и форма отправляет строку JSON:

["js","css","new-value"]

Такой подход применяется при необходимости сохранения сложных структур или передачи данных через API.


Использование FormData и программная отправка

При AJAX-отправке используется объект FormData, который автоматически извлекает значения из DOM:

const form = document.querySelector("#userForm");

form.addEventListener("submit", function(e) {
  e.preventDefault();

  const data = new FormData(form);

  fetch("/api/save", {
    method: "POST",
    body: data
  });
});

Tom Select не требует дополнительной обработки, если используется <select>.

Однако при кастомной конфигурации с JSON-инпутами требуется ручное обновление значения перед отправкой.


Синхронизация состояния перед submit

В некоторых случаях состояние компонента может быть не синхронизировано с DOM, особенно при асинхронных обновлениях (load, create, addOption).

Для гарантированной актуализации данных используется обработка события submit:

const select = new TomSelect("#tags");

document.querySelector("form").addEventListener("submit", function() {
  select.sync();
});

Метод sync() обеспечивает согласование внутреннего состояния и DOM-элементов <option>.


Обработка удалённых данных и remote sources

При использовании загрузки данных с сервера:

new TomSelect("#tags", {
  valueField: "id",
  labelField: "title",
  searchField: "title",
  load: function(query, callback) {
    fetch("/api/tags?q=" + encodeURIComponent(query))
      .then(res => res.json())
      .then(callback);
  }
});

в DOM сохраняются только valueField значения. При отправке формы передается массив идентификаторов:

tags[]=12&tags[]=15

Сами текстовые метки (labelField) в форму не включаются и должны восстанавливаться на сервере.


Особенности сериализации при optgroups

При использовании группировки:

<select id="tags" name="tags[]" multiple>
  <optgroup label="Frontend">
    <option value="react">React</option>
    <option value="vue">Vue</option>
  </optgroup>
</select>

Tom Select сохраняет структуру групп в UI, однако при отправке формы передаются только значения option:

tags[]=react&tags[]=vue

Информация о группах не сериализуется автоматически и требует отдельного поля при необходимости сохранения структуры.


Программное управление значениями перед отправкой

Для сложных сценариев используется явная установка значений:

const select = new TomSelect("#tags");

function prepareSubmit() {
  const values = select.getValue();
  document.querySelector("input[name='tags_snapshot']").value =
    JSON.stringify(values);
}

Такой подход используется при необходимости хранения «снимка состояния» выбора.


Ограничения HTML-сериализации

HTML-форма не передает:

  • текстовые метки (labelField)
  • дополнительные метаданные объектов
  • кастомные поля option (dataset используется только в DOM, но не сериализуется как структура)

Передаются только value атрибуты.

Пример:

{
  id: 10,
  title: "JavaScript",
  category: "language"
}

В форму попадет только:

10

Если требуется передача полного объекта, используется JSON-стратегия через hidden input.


Обработка удаления значений

При использовании remove_button или программного удаления:

select.removeItem("js");

DOM автоматически обновляется:

<option value="js">JavaScript</option>

помечается как не selected, и значение исключается из submit.


Дублирование значений и защита от неконсистентности

При одновременной работе AJAX и формы возможны состояния, при которых DOM и внутреннее состояние расходятся. Для предотвращения таких ситуаций используется принудительное пересоздание DOM-значений:

select.refreshItems();
select.sync();

Это гарантирует корректную сериализацию формы на момент отправки.


Интеграция с серверной валидацией

На сервере значения Tom Select рассматриваются как обычные массивы строк или идентификаторов. Типичная схема обработки:

  • проверка существования ID в базе
  • фильтрация пользовательских значений при disabled create
  • нормализация массива значений

Пример логики:

for each value in tags:
  if value not in database and create_disabled:
    reject value

Комбинированная отправка данных формы

При необходимости передачи как массива значений, так и дополнительных данных применяется комбинированная структура:

<input type="hidden" name="tags_meta">
<select id="tags" name="tags[]" multiple></select>
form.addEventListener("submit", () => {
  const values = select.getValue();
  document.querySelector("[name='tags_meta']").value =
    JSON.stringify(values);
});

В результате сервер получает одновременно:

  • стандартный массив tags[]
  • расширенное поле tags_meta

Поведение при reset формы

При вызове:

form.reset();

native <select> возвращается в исходное состояние, однако Tom Select сохраняет визуальное состояние до синхронизации. Для согласования используется:

select.clear();
select.sync();

Асинхронные изменения перед отправкой

При динамическом добавлении значений непосредственно перед submit:

select.addItem("dynamic-value");

важно учитывать, что добавление происходит синхронно, но обновление DOM может требовать следующего тика выполнения. В сложных сценариях применяется отложенная отправка:

setTimeout(() => form.submit(), 0);

Режимы передачи данных и их влияние на backend

С точки зрения серверной обработки выделяются три основных модели:

  • чистый HTML submit (select multiple)
  • JSON через hidden input
  • гибридная схема (оба варианта одновременно)

Каждая модель определяется архитектурой API:

  • REST API чаще использует JSON
  • server-rendered формы — стандартный URL encoding
  • гибридные системы комбинируют оба подхода

Согласованная работа Tom Select с механизмом отправки форм основана на сохранении стандартной HTML-модели данных, при которой компонент выступает как слой визуализации и управления состоянием, не изменяющий базовый контракт между DOM-формой и серверной обработкой.