Методы обновления интерфейса

Обновление интерфейса в Tom Select опирается на внутреннюю модель состояния экземпляра и набор методов, которые синхронизируют данные (options/items/value) с DOM. В отличие от простого <select>, библиотека поддерживает собственный слой рендеринга, где любое изменение состояния может приводить к частичной или полной переработке UI: списка опций, выбранных элементов, инпута поиска и состояния раскрытия.

Список доступных опций управляется через внутреннюю коллекцию options. Любое изменение этой коллекции требует синхронизации выпадающего меню, иначе интерфейс останется в устаревшем состоянии.

refreshOptions() — ключевой метод, отвечающий за перерисовку списка опций в dropdown.

Он используется, когда:

  • изменился набор options
  • обновился результат поиска (при load)
  • были добавлены или удалены элементы через API
const select = new TomSelect('#select');

select.addOption({ value: '1', text: 'Option 1' });
select.refreshOptions();

Метод не изменяет данные, а только пересобирает DOM-список на основе текущего состояния options. Внутри происходит очистка контейнера dropdown и повторный вызов render-функций для каждой доступной опции.

При работе с динамической загрузкой данных refreshOptions() часто вызывается автоматически после load() или addOption().


clearOptions() полностью очищает список доступных опций.

select.clearOptions();
select.refreshOptions();

После вызова коллекция options становится пустой, а интерфейс dropdown перестаёт отображать элементы. Важно, что это не влияет на уже выбранные значения (items), если они не связаны напрямую с очищаемыми опциями.


updateOption(value, data) применяется для изменения конкретной опции без полной пересборки списка.

select.updateOption('1', {
  value: '1',
  text: 'Updated label'
});

Метод заменяет данные внутри options[value] и при необходимости обновляет DOM-элемент, если он уже отрендерен в выпадающем списке. В зависимости от состояния dropdown может происходить либо точечное обновление, либо отложенная перерисовка при следующем refreshOptions().


Перерисовка выбранных элементов

Отдельным слоем интерфейса являются выбранные элементы (items), отображаемые внутри control-инпута. Их синхронизация управляется через refreshItems().

refreshItems() обновляет отображение выбранных значений.

select.setValue(['1', '2']);
select.refreshItems();

Метод используется, когда:

  • значение изменено программно
  • изменились метаданные выбранных опций
  • требуется синхронизация UI после batch-операций

Внутренне происходит:

  • очистка контейнера выбранных элементов
  • повторное построение DOM для каждого item
  • применение шаблонов item renderer

При частых изменениях значений refreshItems() может вызываться многократно, поэтому библиотека поддерживает оптимизацию через “тихий режим” (silent updates).

select.setValue(['1', '2'], true);

Флаг silent предотвращает автоматический вызов обновления UI, позволяя сгруппировать несколько изменений перед единым refreshItems().


Полная перерисовка интерфейса

Метод render() используется для принудительного пересоздания интерфейсных частей компонента.

select.render('option', select.options['1'], null);

Однако чаще render() применяется косвенно внутри других методов. Он отвечает за генерацию HTML-фрагментов через шаблоны, определённые в конфигурации:

  • option
  • item
  • optgroup_header
  • loading

При кастомизации интерфейса именно render() становится точкой расширения, где можно контролировать HTML каждого элемента.

Принудительный вызов render() применяется редко и обычно в случаях глубокой кастомизации, когда требуется вручную перестроить конкретный узел без изменения состояния.


Синхронизация состояния и UI

Tom Select разделяет логическое состояние и DOM-представление. Основные структуры:

  • options — доступные элементы
  • items — выбранные элементы
  • value — сериализованное значение
  • dropdown_content — контейнер списка
  • control — контейнер выбранных значений

Методы обновления интерфейса всегда опираются на эти структуры.

refreshOptions() работает с options.

refreshItems() работает с items.

setValue() синхронизирует value и items, после чего может инициировать UI-обновление.

select.setValue('1');

При этом последовательность обновления обычно следующая:

  1. обновление внутреннего состояния
  2. пересборка items
  3. обновление input value
  4. опциональная перерисовка dropdown

Управление отображением через setValue и побочные обновления

Хотя setValue() формально не относится к UI-методам, он является триггером обновления интерфейса.

select.setValue(['1', '2']);

При вызове:

  • обновляется this.items
  • пересобирается control UI
  • синхронизируется hidden input
  • при открытом dropdown обновляется подсветка опций

Если передан второй аргумент silent, интерфейс не обновляется автоматически:

select.setValue(['1', '2'], true);
select.refreshItems();

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


Обновление при динамической загрузке

При использовании load() интерфейс обновляется асинхронно. Метод принимает callback, в котором необходимо передать новые опции.

select.load(function(callback) {
  fetch('/api/options')
    .then(res => res.json())
    .then(data => {
      callback(data);
      select.refreshOptions();
    });
});

После выполнения callback:

  • новые данные добавляются в options
  • dropdown пересобирается
  • при открытом списке выполняется перерисовка

Если загрузка происходит при открытом меню, UI обновляется сразу, иначе — откладывается до открытия.


Очистка интерфейса и сброс состояния

Метод clear() влияет одновременно на значения и отображение выбранных элементов.

select.clear();

Внутри происходит:

  • очистка items
  • очистка value
  • обновление control UI
  • очистка input поля

В отличие от clearOptions(), который работает со списком доступных значений, clear() сбрасывает именно выбор пользователя.

Комбинация методов часто используется для полного сброса:

select.clear();
select.clearOptions();
select.refreshOptions();

Принудительная синхронизация интерфейса

В случаях, когда состояние было изменено напрямую (например, через прямую модификацию options), применяется ручная синхронизация:

select.options['1'] = { value: '1', text: 'New' };
select.refreshOptions();

Без вызова refreshOptions() DOM останется в старом состоянии, так как Tom Select не отслеживает глубокие изменения объектов автоматически.


Кэширование и влияние на обновление

Внутренний кэш используется для ускорения рендеринга и поиска. Методы обновления интерфейса могут затрагивать его:

  • refreshOptions() пересобирает отображаемый список, но не всегда очищает кэш поиска
  • clearCache() сбрасывает внутренние закэшированные результаты
select.clearCache();
select.refreshOptions();

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


Поведение интерфейса при открытом dropdown

Особенность обновлений заключается в зависимости от состояния раскрытия списка:

  • если dropdown закрыт — обновления откладываются
  • если открыт — DOM обновляется мгновенно
  • если идет фильтрация — обновляется только видимая часть
select.open();
select.addOption({ value: '3', text: 'Option 3' });
select.refreshOptions();

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


Оптимизация частых обновлений

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

select.setValue(['1', '2', '3'], true);
select.addOption({ value: '4', text: 'Option 4' });
select.addOption({ value: '5', text: 'Option 5' });

select.refreshItems();
select.refreshOptions();

Смысл подхода:

  • минимизация количества reflow/repaint
  • группировка изменений состояния
  • единая финальная синхронизация UI

Взаимодействие refreshOptions и refreshItems

Оба метода часто вызываются совместно, но отвечают за разные части интерфейса.

select.refreshOptions();
select.refreshItems();

Типичный сценарий:

  • изменились опции → обновляется dropdown
  • изменились выбранные значения → обновляется control

Порядок может быть важен, если новые опции влияют на отображение выбранных элементов (например, обновление текста label у уже выбранных items).


Перерисовка через destroy и повторную инициализацию

В крайних случаях, когда интерфейс полностью рассинхронизирован, применяется полный пересоздание экземпляра:

select.destroy();
select = new TomSelect('#select');

Такой подход сбрасывает:

  • DOM-структуру
  • кэш
  • состояние options/items
  • все обработчики событий

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