Система отображения в библиотеке строится вокруг механизма шаблонов
рендеринга, который определяет, как именно выглядят элементы списка,
выбранные значения, группы и вспомогательные состояния. В отличие от
нативного <select>, визуальная часть полностью
контролируется JavaScript-слоем, что позволяет гибко управлять
структурой DOM и содержимым элементов.
Основой служит конфигурация render, а также набор полей
данных, таких как labelField, valueField,
optgroupField, disabledField. Эти параметры
определяют, какие свойства объекта используются при построении
интерфейса.
Каждый элемент данных в списке представляет собой объект:
{
value: "1",
text: "Option 1"
}
Однако в реальных сценариях структура часто расширяется:
{
id: 1,
title: "Option 1",
description: "Дополнительное описание",
category: "group-a"
}
Для корректного отображения требуется настройка:
valueField: поле уникального значенияlabelField: поле отображаемого текстаoptgroupField: поле группировкиПример:
new TomSelect("#select", {
valueField: "id",
labelField: "title",
optgroupField: "category",
searchField: ["title", "description"],
options: [
{ id: 1, title: "Alpha", category: "A" },
{ id: 2, title: "Beta", category: "B" }
]
});
renderКлючевой механизм визуализации — объект render,
содержащий функции-шаблоны. Каждая функция возвращает HTML-строку или
DOM-структуру.
Основные шаблоны:
option — элемент выпадающего спискаitem — выбранный элементoption_create — создание нового элементаoptgroup_header — заголовок группыoptgroup — контейнер группыrender.option)Функция отвечает за внешний вид каждой строки в выпадающем списке.
new TomSelect("#select", {
render: {
option: function(data, escape) {
return `
<div>
<span class="title">${escape(data.title)}</span>
<span class="desc">${escape(data.description)}</span>
</div>
`;
}
}
});
data содержит объект текущей опцииescape используется для защиты от HTML-инъекцийФункция вызывается для каждой опции при открытии dropdown.
render.item)После выбора элемент переносится в область активных значений.
render: {
item: function(data, escape) {
return `<div class="item-selected">
${escape(data.title)}
</div>`;
}
}
option:render.option_create)Если включён режим создания новых значений
(create: true), появляется специальный шаблон.
render: {
option_create: function(data, escape) {
return `<div class="create">Добавить: ${escape(data.input)}</div>`;
}
}
data.input содержит введённый текстoptgroup и optgroup_header)Группы позволяют структурировать список.
new TomSelect("#select", {
optgroups: [
{ value: "A", label: "Группа A" },
{ value: "B", label: "Группа B" }
],
optgroupField: "group"
});
render: {
optgroup_header: function(data, escape) {
return `<div class="group-header">${escape(data.label)}</div>`;
}
}
render: {
optgroup: function(data, escape) {
return `<div class="group">
${data.options_html}
</div>`;
}
}
Функция escape является обязательным инструментом при
построении шаблонов.
Она предотвращает внедрение HTML-кода через данные:
escape("<script>alert(1)</script>")
Результат преобразуется в безопасную строку.
Игнорирование escape допустимо только при полностью
доверенных источниках данных, что в UI-слое считается исключением.
Шаблоны могут содержать произвольную логику:
render: {
option: function(data, escape) {
let status = data.active ? "active" : "inactive";
return `
<div class="option ${status}">
${escape(data.title)}
</div>
`;
}
}
Применяются:
Каждый шаблон напрямую влияет на DOM-структуру:
.option.item.optgroupЭто означает, что стилизация полностью зависит от разработанной разметки.
Пример кастомного layout:
render: {
option: function(data, escape) {
return `
<div class="row">
<div class="col-title">${escape(data.title)}</div>
<div class="col-meta">${escape(data.meta)}</div>
</div>
`;
}
}
Отображение может варьироваться от компактного до расширенного:
render: {
option: (data, escape) => `<div>${escape(data.title)}</div>`
}
render: {
option: (data, escape) => `
<div class="card">
<strong>${escape(data.title)}</strong>
<p>${escape(data.description)}</p>
<small>${escape(data.category)}</small>
</div>
`
}
Хотя render отвечает за HTML, финальный вид определяется
стилями:
Базовая структура классов:
.ts-control.ts-dropdown.option.item.active.selectedПри нестандартных структурах данных отображение полностью зависит от
соответствия labelField и valueField.
new TomSelect("#select", {
labelField: "name",
valueField: "uuid",
searchField: ["name", "tags"]
});
Если поля не заданы корректно, визуальный слой может:
Шаблоны могут изменяться после инициализации:
const control = new TomSelect("#select");
control.settings.render.option = function(data, escape) {
return `<div>${escape(data.title)}</div>`;
};
control.refreshOptions(false);
Поведение:
Несмотря на гибкость, существуют ограничения:
Отображение строится по следующей цепочке:
options)labelField,
valueField)optgroupField)render