Выбор тегов

Механизм тегирования в Tom Select реализует модель расширенного multi-select, в которой пользовательские значения могут не только выбираться из заранее заданного списка, но и динамически создаваться прямо в поле ввода. Такой подход превращает стандартный <select multiple> в интерактивную систему управления сущностями, где каждый введённый элемент интерпретируется как отдельный тег.

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


Включение режима создания тегов

Функциональность тегирования активируется параметром конфигурации:

create: true

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

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


Логика формирования новых значений

Создание тегов опирается на несколько этапов обработки строки ввода:

  1. Захват пользовательского ввода из input-поля
  2. Проверка соответствия существующим значениям
  3. Применение фильтра создания
  4. Нормализация строки
  5. Добавление в коллекцию опций и выбранных значений

Ключевым элементом выступает функция фильтрации:

createFilter: (input) => boolean

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


Нормализация и унификация тегов

При создании новых значений важную роль играет нормализация данных. Она предотвращает дублирование и обеспечивает согласованность хранения.

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

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

Пример внутренней логики:

function normalize(input) {
  return input.trim().replace(/\s+/g, ' ');
}

После нормализации значение сравнивается с существующими элементами коллекции.


Предотвращение дубликатов

Контроль уникальности реализуется на уровне сравнения значений опций. В зависимости от конфигурации используется:

  • строгое сравнение строк
  • сравнение с учётом регистра
  • сравнение по ключевому полю объекта (value)

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

create: true,
persist: true

При отключённой персистентности временные пользовательские значения не сохраняются при перерисовке списка, что влияет на жизненный цикл тегов.


Поддержка разделителей ввода

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

delimiter: ','

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

Дополнительно может использоваться набор разделителей:

delimiter: ',|;'

Это позволяет поддерживать различные сценарии ввода, включая CSV-подобные строки.


Создание тегов при потере фокуса

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

createOnBlur: true

В этом режиме незавершённый ввод автоматически преобразуется в тег. Логика аналогична подтверждению через клавишу Enter, но триггером выступает событие blur.

Такой механизм тесно связан с обработкой состояния input-buffer и требует синхронизации с текущим набором выбранных значений.


Ограничение количества тегов

Контроль объёма выбора реализуется через:

maxItems: 5

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


Внутренняя структура хранения тегов

Каждый тег в Tom Select представляет собой объект:

{
  value: "tag_value",
  text: "Tag Value"
}

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


Кастомное создание значений

Для полного контроля над процессом генерации тегов используется callback:

create: function(input) {
  return {
    value: input,
    text: input
  };
}

Данный механизм позволяет внедрять дополнительную логику:

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

Фильтрация допустимых символов

Ограничение состава вводимых значений реализуется через createFilter:

createFilter: function(input) {
  return /^[a-zA-Z0-9\s-]+$/.test(input);
}

Такая логика предотвращает попадание недопустимых символов в коллекцию тегов и обеспечивает предсказуемость данных.


Взаимодействие с поиском

Режим тегов тесно связан с системой поиска внутри списка. При вводе текста происходит:

  1. Фильтрация существующих опций
  2. Отображение совпадений
  3. Добавление виртуальной опции создания нового элемента

Если совпадений нет, интерфейс может отображать специальное состояние “создать новый элемент”, которое не является отдельной сущностью, а лишь визуальным представлением возможности добавления.


Обновление и удаление тегов

После добавления каждый тег становится частью внутреннего массива items. Управление включает:

  • добавление через addItem
  • удаление через removeItem
  • полную очистку через clear

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


Рендеринг тегов

Отображение тегов формируется через шаблоны:

render: {
  item: function(data) {
    return `<div class="item">${data.text}</div>`;
  }
}

Рендеринг применяется как к предустановленным, так и к пользовательским элементам, поскольку они имеют одинаковую структуру данных.


Обработка событий в режиме тегирования

Система событий охватывает полный жизненный цикл тегов:

  • item_add — добавление тега
  • item_remove — удаление тега
  • option_add — создание новой опции
  • type — ввод текста

Каждое событие позволяет отслеживать изменения состояния и синхронизировать данные с внешними источниками.


Работа с асинхронными источниками

Режим тегов может сочетаться с удалёнными данными. В этом случае пользовательские значения объединяются с результатами API.

При загрузке данных важно различать:

  • серверные опции
  • локально созданные теги

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


Поведение при повторном вводе

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

Сравнение может быть настроено на:

  • строгую идентичность
  • нечувствительность к регистру
  • пользовательский comparator

Особенности сериализации

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

["tag1", "tag2", "tag3"]

Если используется объектная модель, возможна сериализация с сохранением структуры:

[
  { "value": "tag1", "text": "Tag 1" }
]

Выбор формата зависит от конфигурации и интеграции с backend-логикой.


Интеграция с кастомными UI-плагинами

Режим тегирования часто расширяется дополнительными плагинами:

  • удаление через кнопку
  • автоподгон ширины input
  • drag-and-drop сортировка

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


Поведение при очистке поля ввода

После добавления тега input-поле очищается или сохраняет частичный ввод в зависимости от конфигурации. Это влияет на скорость ввода множественных значений и общую модель взаимодействия.


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

Внутренняя модель Tom Select поддерживает строгую синхронизацию между:

  • DOM-отображением
  • внутренним массивом значений
  • набором доступных опций

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