Dropdown Footer представляет собой нижнюю часть выпадающего списка, которая рендерится под всеми опциями и остаётся фиксированной в пределах контейнера dropdown. В архитектуре Tom Select эта область используется как расширяемый слот интерфейса, позволяющий добавлять управляющие элементы, вспомогательную информацию или интерактивные действия, связанные с выбором значений.
Footer выполняет функцию дополнительного UI-слоя, который не участвует в механике выбора напрямую, но влияет на пользовательский сценарий взаимодействия со списком:
В отличие от header, который обычно отвечает за ввод и фильтрацию, footer ориентирован на завершение логики взаимодействия и вспомогательные действия.
Внутренняя структура dropdown в Tom Select строится из трёх основных зон:
Footer рендерится после списка опций, но до закрывающего контейнера dropdown. Это важно для понимания порядка обновления DOM и поведения при виртуализации списка.
Ключевая особенность: footer не пересоздаётся при каждом ререндере options, если он вынесен в отдельный рендер-функционал плагина или кастомного renderer-а.
В Tom Select footer чаще всего реализуется через переопределение
render.dropdown_footer.
new TomSelect("#select", {
render: {
dropdown_footer: function (data, escape) {
return `
<div class="ts-dropdown-footer">
<button type="button" class="ts-action-btn">
Добавить новый элемент
</button>
</div>
`;
}
}
});
Особенности реализации:
escape используется для безопасного вывода
динамического текста;Footer часто зависит от состояния компонента: количества найденных элементов, фильтра, загрузки данных.
new TomSelect("#select", {
load: function (query, callback) {
fetch(`/api/items?q=${encodeURIComponent(query)}`)
.then(res => res.json())
.then(data => callback(data))
.catch(() => callback());
},
render: {
dropdown_footer: function (data, escape) {
const count = data.options ? Object.keys(data.options).length : 0;
return `
<div class="ts-dropdown-footer">
<span class="ts-info">
Найдено: ${escape(count)}
</span>
</div>
`;
}
}
});
Поведение footer в этом случае зависит от объекта data,
который содержит актуальное состояние списка.
Одно из ключевых применений footer — добавление кнопок управления списком.
new TomSelect("#select", {
persist: false,
render: {
dropdown_footer: function () {
return `
<div class="ts-dropdown-footer">
<button type="button" class="add-item-btn">
+ Создать новый элемент
</button>
</div>
`;
}
},
onInitialize: function () {
this.dropdown_content.addEventListener("click", (e) => {
if (e.target.classList.contains("add-item-btn")) {
const value = prompt("Введите значение");
if (value) {
this.addOption({ value, text: value });
this.addItem(value);
}
}
});
}
});
Особенность такого подхода заключается в том, что footer остаётся частью dropdown DOM, поэтому делегирование событий предпочтительнее прямых обработчиков.
Footer часто используется для отображения системных состояний:
new TomSelect("#select", {
render: {
dropdown_footer: function (data) {
if (this.loading) {
return `<div class="ts-dropdown-footer">Загрузка...</div>`;
}
if (!data.options || Object.keys(data.options).length === 0) {
return `<div class="ts-dropdown-footer">Нет данных</div>`;
}
return `<div class="ts-dropdown-footer">Готово к выбору</div>`;
}
}
});
Здесь footer становится реактивным индикатором состояния компонента, хотя сам по себе не является reactive-системой — обновление происходит через перерисовку dropdown.
CSS-уровень играет ключевую роль в визуальной интеграции footer с остальной частью dropdown.
.ts-dropdown-footer {
padding: 8px 10px;
border-top: 1px solid #e5e5e5;
background: #fafafa;
font-size: 12px;
display: flex;
justify-content: space-between;
align-items: center;
}
.ts-dropdown-footer .ts-action-btn {
background: none;
border: none;
color: #2b7cff;
cursor: pointer;
}
.ts-dropdown-footer .ts-action-btn:hover {
text-decoration: underline;
}
Важные моменты:
Dropdown в Tom Select часто ограничен по высоте, поэтому footer становится частью scroll-контейнера.
Это приводит к важному поведению:
Пример закрепления footer:
.ts-dropdown {
display: flex;
flex-direction: column;
}
.ts-dropdown-content {
overflow-y: auto;
flex: 1;
}
.ts-dropdown-footer {
position: sticky;
bottom: 0;
}
Такой подход превращает footer в фиксированную панель действий внутри dropdown.
Плагины Tom Select могут модифицировать поведение footer:
dropdown_input может перемещать input выше
footer;virtual_scroll влияет на необходимость фиксации
footer;При создании расширений важно учитывать порядок рендера:
Нарушение этого порядка приводит к визуальным артефактам и потере событий.
В сложных интерфейсах footer может разделяться на несколько зон логически, хотя физически остаётся одним блоком:
render: {
dropdown_footer: function () {
return `
<div class="ts-dropdown-footer">
<div class="footer-stats">Результаты обновлены</div>
<div class="footer-actions">
<button class="reload-btn">Обновить</button>
<button class="clear-btn">Очистить</button>
</div>
</div>
`;
}
}
Такой подход позволяет:
При изменении состояния компонента происходит пересборка dropdown:
Внутренне это связано с повторным вызовом render-функций, что делает
footer зависимым от текущего контекста
TomSelectInstance.
Footer в Tom Select имеет ряд ограничений:
При этом архитектура остаётся предсказуемой: footer всегда является частью DOM dropdown и не отделяется в отдельный слой компонента.