Data-атрибуты

В основе интеграции с HTML-формами Tom Select опирается на стандартный <select> элемент и его <option> узлы. Любые data-* атрибуты, добавленные к <option>, автоматически попадают в объект данных элемента и становятся доступны внутри экземпляра селекта.

Каждый <option> рассматривается не только как пара value → text, но и как контейнер расширенных метаданных. Это позволяет хранить произвольные поля прямо в DOM без необходимости отдельного источника данных.

<select id="countries">
  <option value="kz" data-code="KZ" data-population="19000000">
    Kazakhstan
  </option>
  <option value="de" data-code="DE" data-population="83000000">
    Germany
  </option>
</select>

При инициализации Tom Select извлекает:

  • value → идентификатор
  • текст узла → отображаемое имя
  • data-* → дополнительные поля объекта

Как Tom Select преобразует data-атрибуты в объект данных

При парсинге DOM каждый <option> конвертируется в объект вида:

{
  value: "kz",
  text: "Kazakhstan",
  code: "KZ",
  population: "19000000"
}

Все атрибуты data-code, data-population становятся свойствами объекта без префикса data-.

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


Доступ к data-полям через API экземпляра

После инициализации доступ к расширенным полям осуществляется через внутренние структуры Tom Select.

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

const item = select.options["kz"];

console.log(item.code); // "KZ"
console.log(item.population); // "19000000"

Каждая запись хранится в select.options, где ключ — это value, а значение — полный объект с метаданными.


Использование data-атрибутов в кастомном рендеринге

Одно из ключевых применений data-атрибутов — формирование пользовательского интерфейса через render.

new TomSelect("#countries", {
  render: {
    option: function(data, escape) {
      return `
        <div>
          <span>${escape(data.text)}</span>
          <small>${escape(data.code)}</small>
        </div>
      `;
    },
    item: function(data, escape) {
      return `<div>${escape(data.text)} (${escape(data.code)})</div>`;
    }
  }
});

Здесь data.code и любые другие data-* поля становятся частью шаблона без дополнительной обработки.


Динамическое создание элементов с дополнительными данными

При добавлении новых элементов через API можно передавать дополнительные поля вручную:

select.addOption({
  value: "fr",
  text: "France",
  code: "FR",
  population: 67000000
});

Tom Select не ограничивает структуру объекта, поэтому любые поля сохраняются в options.


Синхронизация data-атрибутов и value-структуры

При выборе элемента возвращается только value, однако полный объект доступен через API:

select.on("change", (value) => {
  const data = select.options[value];

  console.log(data);
});

Это делает data-атрибуты основным способом расширения модели данных без изменения формы.


Особенности работы с boolean и числовыми значениями

HTML не хранит типы, поэтому:

<option value="1" data-active="true" data-score="42">

будет преобразовано в:

{
  value: "1",
  active: "true",
  score: "42"
}

Для восстановления типов требуется постобработка:

const normalize = (item) => ({
  ...item,
  active: item.active === "true",
  score: Number(item.score)
});

Группы (optgroup) и data-атрибуты

Tom Select поддерживает передачу метаданных и на уровне групп.

<optgroup label="Europe" data-region="EU">
  <option value="de">Germany</option>
  <option value="fr">France</option>
</optgroup>

При парсинге optgroup также может содержать дополнительные свойства:

{
  label: "Europe",
  region: "EU"
}

Это позволяет реализовать фильтрацию и визуальную сегментацию интерфейса.


Передача кастомных данных через AJAX

При использовании удалённых источников данных структура аналогична HTML-версии:

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

Каждый объект в items может содержать любые поля:

{
  "value": "kz",
  "text": "Kazakhstan",
  "code": "KZ",
  "continent": "Asia"
}

Эти поля становятся доступными так же, как и из data-*.


Использование dataset-объектов внутри DOM-элементов

Хотя Tom Select преобразует data-* в объект, исходный DOM сохраняется и может быть получен:

const option = document.querySelector("#countries option[value='kz']");

console.log(option.dataset.code);
console.log(option.dataset.population);

dataset используется как промежуточный слой между HTML и внутренней моделью данных.


Обновление data-атрибутов после инициализации

Изменение DOM напрямую не всегда синхронизируется автоматически. Например:

const option = document.querySelector("option[value='kz']");
option.dataset.code = "KAZ";

Tom Select не обновит options автоматически. Требуется явное обновление:

select.updateOption("kz", {
  ...select.options["kz"],
  code: "KAZ"
});

Использование data-атрибутов для фильтрации

Расширенные поля часто используются для кастомной логики поиска:

new TomSelect("#countries", {
  score: function(search) {
    return function(item) {
      let score = 1;

      if (item.code && item.code.includes(search.toUpperCase())) {
        score += 10;
      }

      if (item.text.toLowerCase().includes(search.toLowerCase())) {
        score += 5;
      }

      return score;
    };
  }
});

Здесь code — поле, полученное из data-code, становится частью алгоритма ранжирования.


Влияние data-атрибутов на создание новых элементов пользователем

При включённой опции создания элементов (create: true) можно автоматически добавлять дополнительные поля:

new TomSelect("#countries", {
  create: function(input) {
    return {
      value: input.toLowerCase(),
      text: input,
      created: true
    };
  }
});

Добавленное поле created работает как маркер, аналогичный data-*.


Сериализация данных с учётом data-атрибутов

При получении значений через getValue() возвращается только value, но расширенные данные можно восстановить вручную:

const values = select.getValue();

const fullData = values.map(v => select.options[v]);

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


Ограничения и особенности архитектуры data-модели

Несмотря на гибкость, модель имеет ряд особенностей:

  • все data-* значения строковые по умолчанию
  • синхронизация DOM → JS односторонняя после инициализации
  • обновление требует использования API Tom Select
  • сложные вложенные структуры в data-атрибутах невозможны без сериализации (JSON)

Для хранения сложных объектов применяется подход:

<option value="kz" data-meta='{"code":"KZ","population":19000000}'>

с последующим парсингом:

const meta = JSON.parse(item.meta);

Практическая модель расширения данных через data-атрибуты

Использование data-атрибутов в Tom Select формирует устойчивый паттерн:

  • HTML хранит базовые и дополнительные поля
  • Tom Select превращает их в объектную модель
  • API работает с единым источником данных
  • UI получает доступ к расширенной информации без дополнительных запросов

Такая структура позволяет использовать компонент как легковесный data-layer поверх стандартного <select> без необходимости внедрения внешнего state-менеджера