Управление выбранными элементами

В библиотеке Tom Select управление выбранными значениями строится вокруг единообразной модели данных, независимо от режима работы (single, multiple, create). В основе лежит коллекция выбранных items, где каждый элемент представлен объектом с минимальной структурой:

  • value — уникальный идентификатор
  • text — отображаемая строка
  • дополнительные поля (опционально, из data-* или кастомных источников)

Внутренне Tom Select хранит выбранные элементы в состоянии инстанса, синхронизируя его с DOM и оригинальным <select>.

Ключевой принцип: источник истины — состояние компонента, а не DOM.


Добавление выбранных элементов

Добавление значения выполняется через метод addItem. Он работает как с существующими опциями, так и с динамически создаваемыми значениями (при включённом create).

Базовое добавление

const ts = new TomSelect('#select');

ts.addItem('value1');

При вызове происходит последовательность действий:

  1. Проверка существования значения
  2. Поиск соответствующей опции в списке
  3. Создание новой записи в выбранных элементах
  4. Обновление UI
  5. Синхронизация с оригинальным <select>

Добавление с объектом данных

При использовании кастомных источников данных:

ts.addItem('v2', true);

Второй аргумент может управлять поведением поиска опции. При отсутствии совпадения возможно создание нового элемента (если разрешено конфигурацией).


Массовое добавление

Для режима multiple:

ts.addItems(['a', 'b', 'c']);

Механика:

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

Удаление выбранных элементов

Удаление осуществляется через метод removeItem.

ts.removeItem('value1');

Поведение при удалении

При удалении:

  1. Элемент исключается из внутреннего массива selected
  2. UI-тег удаляется из контейнера
  3. Обновляется состояние оригинального <select>
  4. Вызываются события изменения

Удаление всех значений

ts.clear();

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

  • очищает массив selectedItems
  • сбрасывает визуальные элементы
  • сохраняет список доступных опций
  • не удаляет сами опции

Получение выбранных значений

Получение массива значений

ts.getValue();

В режиме multiple возвращает массив строк:

["a", "b", "c"]

В single-режиме возвращается строка или null.


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

ts.getSelectedOptions();

Каждый элемент содержит:

  • value
  • text
  • оригинальный DOM-узел (если присутствует)

Синхронизация с DOM <select>

Tom Select поддерживает двустороннюю синхронизацию:

  • изменения через API → обновляют <select>
  • изменения <select> → могут отражаться в Tom Select (если не отключено)

Принцип синхронизации

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

  1. Обновляется selectedIndex или selectedOptions
  2. Перестраивается внутренний state
  3. Триггерится событие change

Пример ручного вмешательства

const select = document.querySelector('#select');

select.value = 'newValue';
select.dispatchEvent(new Event('change'));

Tom Select перехватит событие и синхронизирует состояние.


Поведение в режиме multiple

В multiple-режиме выбранные элементы представлены как набор независимых тегов.

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

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

Управление порядком

Удаление и повторное добавление может менять порядок:

ts.removeItem('a');
ts.addItem('a');

Ограничения и защита от некорректных состояний

Внутренние механизмы предотвращают:

Дубликаты

Если значение уже выбрано:

  • повторное добавление игнорируется
  • UI не изменяется

Несуществующие значения

При попытке добавить несуществующую опцию:

  • поведение зависит от create
  • при create: false операция отклоняется
  • при create: true создаётся новая опция

Несоответствие типов

Все значения приводятся к строковому виду:

  • "1" и 1 считаются одинаковыми
  • строгая типизация отсутствует на уровне value

События при изменении выбранных элементов

Каждое изменение вызывает цепочку событий.

Основные события

  • change — общее изменение состояния
  • item_add — добавление элемента
  • item_remove — удаление элемента

Пример обработки

ts.on('item_add', function(value){
    console.log('Добавлено:', value);
});

Внутренний порядок вызовов

При добавлении:

  1. addItem
  2. обновление state
  3. DOM update
  4. item_add
  5. change

Работа с кастомными render-опциями

Выбранные элементы могут иметь пользовательское отображение через render.item.

new TomSelect('#select', {
    render: {
        item: function(data) {
            return `<div class="item">${data.text}</div>`;
        }
    }
});

Влияние на управление

  • рендер не влияет на value
  • состояние остаётся неизменным
  • UI полностью отделён от логики

Программное управление состоянием

Полная замена выбранных значений

ts.setValue(['x', 'y']);

Поведение:

  • старые значения очищаются
  • новые добавляются атомарно
  • вызывается единое событие изменения

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

ts.sync();

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

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

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

При отправке формы <select> с Tom Select ведёт себя как стандартный input:

  • single → одно значение
  • multiple → несколько значений
const formData = new FormData(form);

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


Особенности жизненного цикла выбранных элементов

Каждый выбранный элемент проходит стадии:

  1. Поиск или создание опции
  2. Добавление в state
  3. Создание DOM-узла
  4. Привязка событий
  5. Отображение в UI

При удалении процесс обратный:

  1. Удаление DOM-узла
  2. Удаление из state
  3. Обновление <select>
  4. События удаления

Управление состоянием через API-интерфейс

Основные методы:

  • addItem(value)
  • addItems(values[])
  • removeItem(value)
  • clear()
  • setValue(values)
  • getValue()

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


Поведение при асинхронных данных

При загрузке опций через AJAX:

  • добавление выбранных элементов может происходить до полной загрузки списка
  • Tom Select временно хранит значения как “pending”
  • после загрузки происходит резолвинг значений в полноценные опции

Конфликты состояния и их разрешение

Возможные сценарии:

Опция удалена после выбора

  • значение остаётся в selectedItems
  • UI отображает текст без привязки к опции
  • при следующей синхронизации может быть удалено

Повторная инициализация

При повторной инициализации:

  • старое состояние может быть восстановлено из <select>
  • либо перезаписано через value

Контроль целостности данных

Tom Select не допускает:

  • несоответствия между UI и state
  • расхождения между <select> и внутренним списком
  • дублирования идентификаторов

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