Работа с HTML внутри опций в Slim Select требует понимания того, как
библиотека обрабатывает данные элемента <select> и
каким образом формируется DOM-структура выпадающего списка. В отличие от
стандартного HTML <select>, где содержимое
<option> интерпретируется как текст, Slim Select
предоставляет расширенный слой рендеринга, позволяющий использовать
HTML-разметку в элементах списка и в выбранном значении.
Slim Select опирается не на DOM <option> напрямую,
а на внутреннюю структуру данных:
{
text: 'Отображаемый текст',
value: 'unique-value'
}
При этом text по умолчанию интерпретируется как строка и
экранируется при выводе. Это означает, что HTML внутри text
не будет выполнен, а отобразится как обычный текст.
Для поддержки HTML Slim Select использует расширенное поле:
{
text: 'Обычный текст',
html: '<strong>HTML текст</strong>',
value: '1'
}
Именно html становится ключевым механизмом включения
разметки в опции.
При использовании массива данных HTML может быть задан напрямую:
new SlimSelect({
select: '#select',
data: [
{
value: '1',
text: 'Google',
html: '<span class="option option--google">Google</span>'
},
{
value: '2',
text: 'Facebook',
html: '<span class="option option--facebook">Facebook</span>'
}
]
})
В этом случае Slim Select использует html для рендера
выпадающего списка, а text — как fallback и как источник
для поиска.
Поиск по списку выполняется по text, а не по
html. Это важное поведение, которое позволяет:
При открытии списка Slim Select формирует структуру примерно следующего вида:
<div class="ss-option">
<span class="option option--google">Google</span>
</div>
Если html не задан, используется:
<div class="ss-option">Google</div>
Таким образом, HTML внедряется не в <option>, а в
отдельный контейнер внутри компонента.
Slim Select позволяет переопределять шаблоны рендера через
конфигурации template (в зависимости от версии API).
Основные точки расширения:
optionselectedgroupПример кастомного рендера опции:
new SlimSelect({
select: '#select',
data: [
{ value: '1', text: 'HTML' },
{ value: '2', text: 'CSS' }
],
template: {
option: (option) => {
return `<div class="custom-option">
<span class="label">${option.text}</span>
</div>`
},
selected: (option) => {
return `<div class="custom-selected">
${option.text}
</div>`
}
}
})
В этом режиме библиотека перестает ограничиваться стандартным отображением и полностью делегирует HTML-структуру разработчику.
HTML в опциях чаще всего используется для добавления визуальных элементов:
{
value: 'ru',
text: 'Русский',
html: `<div class="lang-option">
<img src="/flags/ru.svg" class="flag">
<span>Русский</span>
</div>`
},
{
value: 'en',
text: 'English',
html: `<div class="lang-option">
<img src="/flags/gb.svg" class="flag">
<span>English</span>
</div>`
}
Такой подход позволяет создавать интерфейсы уровня UI-kit без необходимости писать отдельный компонент.
Несмотря на гибкость, HTML в Slim Select имеет ряд ограничений:
Поиск всегда работает только по text:
Если внутри html используются интерактивные элементы
(кнопки, ссылки), они могут не получать корректные события без
дополнительной обработки через делегирование DOM.
При изменении состояния select Slim Select пересоздает DOM-элементы, поэтому любые прямые манипуляции с внутренним HTML могут быть потеряны.
Использование HTML в опциях открывает потенциальный риск внедрения скриптов. Поэтому критически важно учитывать источник данных.
Slim Select не выполняет полноценную санитизацию HTML, поэтому:
htmlПример небезопасного подхода:
{
value: '1',
text: userInput,
html: `<div>${userInput}</div>`
}
Корректный подход:
function escapeHtml(str) {
return str
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
}
{
value: '1',
text: escapeHtml(userInput),
html: `<div>${escapeHtml(userInput)}</div>`
}
Наиболее стабильная модель использования:
text — для логики (поиск, значение, fallback)html — для визуального отображения{
value: 'admin',
text: 'Administrator',
html: `<div class="role role--admin">
<span class="badge">A</span>
Administrator
</div>`
}
Такое разделение позволяет сохранить предсказуемость поведения компонента при любых сценариях обновления данных.
При изменении данных через API Slim Select HTML обновляется вместе с опциями:
const select = new SlimSelect({
select: '#select',
data: []
})
select.setData([
{
value: '1',
text: 'New item',
html: '<strong>New item</strong>'
}
])
При каждом вызове setData происходит полная переразметка
списка, включая HTML-узлы.
Если html не задан, используется text:
{
value: '1',
text: '<b>Bold</b>'
}
Результат будет отображен как текст:
<b>Bold</b>
Это поведение предотвращает случайное выполнение HTML при отсутствии
явного разрешения через html.
HTML-опции часто используются для построения:
Пример тарифов:
{
value: 'free',
text: 'Free',
html: `<div class="plan plan--free">
<span>Free</span>
<small>Basic features</small>
</div>`
},
{
value: 'pro',
text: 'Pro',
html: `<div class="plan plan--pro">
<span>Pro</span>
<small>Advanced tools</small>
<span class="badge">Popular</span>
</div>`
}
Такой подход превращает обычный <select> в
полноценный компонент интерфейса с кастомной версткой и семантической
логикой.