Отправка данных формы с интегрированным компонентом 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.
При включенной опции создания новых элементов:
new TomSelect("#tags", {
create: true
});
пользовательские значения не присутствуют в исходном списке
<option>. Tom Select динамически добавляет их в
DOM:
<option value="new-value" selected>new-value</option>
Таким образом, даже пользовательские значения становятся частью стандартной HTML-сериализации.
Особенность этого режима заключается в том, что сервер не различает заранее определённые и пользовательские значения без дополнительной логики.
В ряде конфигураций используется скрытый <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.
При 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-инпутами требуется ручное обновление значения перед отправкой.
В некоторых случаях состояние компонента может быть не
синхронизировано с DOM, особенно при асинхронных обновлениях
(load, create, addOption).
Для гарантированной актуализации данных используется обработка
события submit:
const select = new TomSelect("#tags");
document.querySelector("form").addEventListener("submit", function() {
select.sync();
});
Метод sync() обеспечивает согласование внутреннего
состояния и DOM-элементов <option>.
При использовании загрузки данных с сервера:
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) в форму не включаются
и должны восстанавливаться на сервере.
При использовании группировки:
<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-форма не передает:
labelField)Передаются только 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 рассматриваются как обычные массивы строк или идентификаторов. Типичная схема обработки:
Пример логики:
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При вызове:
form.reset();
native <select> возвращается в исходное состояние,
однако Tom Select сохраняет визуальное состояние до синхронизации. Для
согласования используется:
select.clear();
select.sync();
При динамическом добавлении значений непосредственно перед submit:
select.addItem("dynamic-value");
важно учитывать, что добавление происходит синхронно, но обновление DOM может требовать следующего тика выполнения. В сложных сценариях применяется отложенная отправка:
setTimeout(() => form.submit(), 0);
С точки зрения серверной обработки выделяются три основных модели:
select multiple)Каждая модель определяется архитектурой API:
Согласованная работа Tom Select с механизмом отправки форм основана на сохранении стандартной HTML-модели данных, при которой компонент выступает как слой визуализации и управления состоянием, не изменяющий базовый контракт между DOM-формой и серверной обработкой.