Прослушивание событий

Библиотека Tom Select построена вокруг событийной модели, позволяющей реагировать на изменения состояния компонента без необходимости модифицировать внутреннюю логику. Все ключевые действия — выбор значений, ввод текста, загрузка данных, открытие и закрытие выпадающего списка — транслируются в набор событий, которые можно перехватывать через единый API.

Основной механизм подписки реализован через метод:

tomSelect.on(eventName, handler)

Удаление обработчика:

tomSelect.off(eventName, handler)

События исполняются в контексте экземпляра Tom Select, что позволяет внутри обработчиков обращаться к текущему состоянию компонента через this.


Базовые события изменения выбора

change

Событие change вызывается при любом изменении значения поля, включая добавление и удаление элементов.

const ts = new TomSelect("#select", {
  onChange(value) {
    console.log("Текущее значение:", value);
  }
});

Эквивалент через событийный API:

ts.on("change", (value) => {
  console.log(value);
});

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

  • передаёт текущее значение (строка или массив)
  • вызывается после синхронизации внутреннего состояния
  • не различает тип изменения (добавление/удаление)

item_add

Событие item_add срабатывает при добавлении нового элемента в выбранные значения.

ts.on("item_add", (value, item) => {
  console.log("Добавлен элемент:", value);
  console.log("DOM-элемент:", item);
});

Параметры:

  • value — значение добавленного элемента
  • item — HTML-узел элемента в интерфейсе

Используется для:

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

item_remove

Событие удаления выбранного элемента.

ts.on("item_remove", (value, item) => {
  console.log("Удалён элемент:", value);
});

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

  • вызывается до окончательного обновления списка значений
  • DOM-элемент ещё может быть доступен в момент вызова

События работы с вводом текста

type

Событие type генерируется при вводе текста в поле поиска.

ts.on("type", (query) => {
  console.log("Пользователь ввёл:", query);
});

Характеристики:

  • вызывается на каждый ввод символа
  • используется для кастомной фильтрации
  • может вызываться очень часто, требует оптимизации (debounce/throttle)

Пример с задержкой:

let timeout;

ts.on("type", (query) => {
  clearTimeout(timeout);

  timeout = setTimeout(() => {
    console.log("Запрос к серверу:", query);
  }, 300);
});

События открытия и закрытия выпадающего списка

Срабатывает при открытии списка опций.

ts.on("dropdown_open", () => {
  console.log("Список открыт");
});

Используется для:

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

Срабатывает при закрытии выпадающего списка.

ts.on("dropdown_close", () => {
  console.log("Список закрыт");
});

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

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

События загрузки данных

load

Событие load используется в конфигурациях с удалённой загрузкой (load callback или loadThrottle).

const ts = new TomSelect("#select", {
  load: function(query, callback) {
    fetch(`/api?q=${query}`)
      .then(res => res.json())
      .then(data => callback(data));
  }
});

ts.on("load", (options) => {
  console.log("Загружены данные:", options);
});

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

  • вызывается после получения данных
  • передаёт массив загруженных опций
  • может использоваться для кеширования

error

Событие обработки ошибок загрузки или внутренней логики.

ts.on("error", (error) => {
  console.error("Ошибка Tom Select:", error);
});

Применение:

  • логирование ошибок API
  • отображение пользовательских уведомлений
  • fallback-логика

События инициализации и жизненного цикла

initialize

Срабатывает после полной инициализации компонента.

ts.on("initialize", () => {
  console.log("Tom Select готов");
});

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

  • вызывается один раз
  • гарантирует завершение построения DOM и внутренних структур

destroy

Событие уничтожения экземпляра.

ts.on("destroy", () => {
  console.log("Компонент уничтожен");
});

Используется для:

  • очистки подписок
  • освобождения ресурсов
  • синхронизации с внешними системами

События управления опциями

option_add

Добавление новой опции в список доступных значений.

ts.on("option_add", (value, data) => {
  console.log("Добавлена опция:", value, data);
});

option_remove

Удаление опции из списка.

ts.on("option_remove", (value) => {
  console.log("Удалена опция:", value);
});

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


События очистки и сброса

clear

Срабатывает при очистке выбранных значений.

ts.on("clear", () => {
  console.log("Выбор очищен");
});

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

  • вызывается при clear() и пользовательской очистке
  • не вызывает change напрямую, но обычно сопровождается им

Приоритет и порядок вызова событий

Tom Select вызывает события последовательно, в зависимости от внутреннего потока операций:

  1. пользовательское действие (клик, ввод)
  2. обновление состояния
  3. синхронизация DOM
  4. вызов событий (item_add, item_remove, change и т.д.)

Понимание порядка важно при построении сложных реактивных систем, где несколько обработчиков могут влиять друг на друга.


Контекст исполнения обработчиков

В обработчиках событий this указывает на экземпляр Tom Select:

ts.on("change", function(value) {
  console.log(this.items);
});

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

ts.on("change", (value) => {
  console.log(this); // не Tom Select
});

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


Массовая обработка событий

При работе с несколькими событиями применяется цепочка подписок:

ts.on("change", handler)
  .on("item_add", handler)
  .on("item_remove", handler);

Либо централизованная регистрация:

const handlers = {
  change(value) {},
  item_add(value) {},
  item_remove(value) {}
};

Object.entries(handlers).forEach(([event, fn]) => {
  ts.on(event, fn);
});

Удаление подписок и управление памятью

Корректное удаление обработчиков предотвращает утечки памяти:

function onChange(value) {
  console.log(value);
}

ts.on("change", onChange);

// позже
ts.off("change", onChange);

При уничтожении экземпляра рекомендуется явно снимать критические подписки, особенно если Tom Select интегрирован в SPA-архитектуру.


Комбинирование событий для реактивной логики

Сложные сценарии строятся на комбинации событий:

ts.on("item_add", () => updateState());
ts.on("item_remove", () => updateState());
ts.on("clear", () => resetState());

Такой подход позволяет:

  • синхронизировать UI и внешнее состояние
  • избегать прямого вмешательства в внутреннюю логику библиотеки
  • поддерживать декларативную модель обработки изменений

Особенности частых событий и производительность

События type и change могут вызываться часто при активном вводе. Для оптимизации применяются:

  • debounce
  • кэширование результатов поиска
  • ограничение частоты сетевых запросов
let timer;

ts.on("type", (query) => {
  clearTimeout(timer);

  timer = setTimeout(() => {
    performSearch(query);
  }, 250);
});

Событийная модель как основа расширения поведения

Система событий Tom Select позволяет полностью переопределять поведение без модификации исходного кода. Через комбинацию item_add, item_remove, change, load и type реализуются:

  • кастомные автокомплиты
  • интеграция с REST API
  • синхронизация с Vue/React/Redux-подобными хранилищами
  • сложные сценарии валидации выбора

Событийный слой выступает основным интерфейсом взаимодействия между внутренним состоянием компонента и внешней логикой приложения.