Интеграция с HTML формами

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

После инициализации Tom Select исходный <select> либо скрывается, либо визуально заменяется, однако остаётся частью DOM-структуры формы. Это обеспечивает совместимость с механизмом отправки данных через FormData и стандартный submit-процесс.


Базовая интеграция с формой

Обычная HTML-форма с подключённым Tom Select не требует изменения логики отправки:

<form action="/submit" method="POST">
  <label for="country">Страна</label>
  <select id="country" name="country">
    <option value="kz">Kazakhstan</option>
    <option value="ru">Russia</option>
    <option value="de">Germany</option>
  </select>

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

<script>
  new TomSelect("#country");
</script>

Ключевое поведение:

  • значение выбирается через UI Tom Select
  • при отправке формы используется стандартное значение <select>
  • атрибут name остаётся определяющим для backend

Работа с множественным выбором

При использовании multiple поведение формы изменяется: браузер отправляет массив значений.

<form method="POST">
  <select id="tags" name="tags[]" multiple>
    <option value="js">JavaScript</option>
    <option value="css">CSS</option>
    <option value="html">HTML</option>
  </select>

  <button type="submit">Save</button>
</form>

<script>
  new TomSelect("#tags");
</script>

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

  • имя поля часто задаётся как tags[] для серверных языков (PHP, Laravel, Express middleware)
  • каждый выбранный элемент отправляется как отдельное значение
  • порядок значений сохраняется в зависимости от конфигурации plugins и пользовательских действий

Синхронизация состояния формы

Tom Select синхронизирует состояние между DOM и внутренним состоянием компонента:

  • изменение через UI → обновление <select>
  • изменение через JavaScript → обновление UI
  • reset формы → сброс состояния Tom Select

Пример программного изменения значения

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

select.setValue("ru");

В этом случае:

  • DOM <select> получает новое значение
  • при submit будет отправлено обновлённое значение
  • UI обновляется автоматически

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

HTML-форма при вызове form.reset() сбрасывает значения нативных элементов, но Tom Select требует синхронизации состояния.

<form id="myForm">
  <select id="city" name="city">
    <option value="almaty">Almaty</option>
    <option value="astana">Astana</option>
  </select>

  <button type="reset">Reset</button>
</form>

<script>
  const select = new TomSelect("#city");

  document.getElementById("myForm").addEventListener("reset", () => {
    setTimeout(() => {
      select.clear();
    }, 0);
  });
</script>

Причина использования setTimeout:

  • reset срабатывает до обновления DOM
  • Tom Select должен перезаписать внутреннее состояние после сброса формы

Валидация HTML5 и интеграция с required

Tom Select сохраняет участие в нативной HTML5-валидации, включая required, min, max (для числовых кастомных реализаций), и pattern через кастомные решения.

<form>
  <select id="language" name="language" required>
    <option value="">Select...</option>
    <option value="en">English</option>
    <option value="ru">Russian</option>
  </select>

  <button type="submit">Send</button>
</form>

<script>
  new TomSelect("#language");
</script>

Поведение:

  • если значение пустое → форма не отправляется
  • браузер отображает стандартное сообщение валидации
  • Tom Select не отключает constraint validation API

Работа с hidden input и кастомной сериализацией

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

<form id="form">
  <input type="hidden" name="user_role" id="user_role">

  <div id="role_select"></div>

  <button type="submit">OK</button>
</form>

<script>
  const select = new TomSelect("#role_select", {
    options: [
      { value: "admin", text: "Admin" },
      { value: "user", text: "User" }
    ],
    onChange(value) {
      document.querySelector("#user_role").value = value;
    }
  });
</script>

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

  • данные полностью контролируются JavaScript
  • форма не зависит от <select>
  • удобно для сложных API-моделей

Интеграция с FormData API

При отправке формы через FormData Tom Select не требует дополнительной обработки.

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

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

  const data = new FormData(form);

  console.log(data.get("country"));
});

Поведение:

  • одиночный select → строка
  • multiple select → первое значение через get, полный список через getAll

Динамическое создание элементов в форме

Tom Select поддерживает добавление новых значений, которые также участвуют в submit-процессе.

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

Влияние на форму:

  • созданные элементы добавляются в <select> как <option>
  • отправляются как обычные значения
  • сервер не различает источник значения (predefined или created)

Поведение при disabled состоянии

const select = new TomSelect("#country");
select.disable();

Эффект:

  • поле исключается из отправки формы
  • пользователь не может изменять значение
  • значение остаётся в DOM, но игнорируется при submit

Динамическое обновление options в форме

При изменении списка опций необходимо учитывать синхронизацию с формой:

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

select.addOption({ value: "shymkent", text: "Shymkent" });
select.refreshOptions(false);

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


Поведение при нескольких Tom Select в одной форме

При наличии нескольких инстансов:

<form>
  <select id="a" name="a"></select>
  <select id="b" name="b"></select>
</form>

<script>
  new TomSelect("#a");
  new TomSelect("#b");
</script>

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

  • каждый инстанс управляет собственным DOM-узлом
  • конфликтов имен не возникает при корректном name
  • submit обрабатывается стандартным способом

Управление отправкой формы через события Tom Select

Хотя библиотека не вмешивается в submit, она предоставляет события для синхронизации:

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

select.on("change", (value) => {
  console.log("changed:", value);
});

Использование:

  • подготовка данных перед отправкой
  • валидация зависимых полей
  • динамическое обновление состояния формы

Особенности работы с AJAX-формами

При отправке через AJAX важно учитывать актуальность состояния:

form.addEventListener("submit", async (e) => {
  e.preventDefault();

  const formData = new FormData(form);

  await fetch("/api", {
    method: "POST",
    body: formData
  });
});

Tom Select уже синхронизировал DOM, поэтому дополнительных преобразований не требуется.


Совместимость с нестандартными формами

В сложных интерфейсах (SPA, модальные окна, динамические формы) Tom Select сохраняет поведение формы при условии:

  • элемент находится внутри <form>
  • не удаляется из DOM до submit
  • корректно инициализирован до взаимодействия пользователя

При нарушении этих условий требуется ручная синхронизация состояния через API setValue, clear, getValue.