В Choices.js текстовые сообщения интерфейса и шаблоны отображения элементов формируются через набор конфигурационных параметров и callback-функций, позволяющих полностью контролировать HTML-разметку списка, выбранных значений и системных сообщений компонента.
Формирование визуального представления в Choices.js строится вокруг функций, возвращающих строки HTML. Основные точки расширения:
itemTemplate — шаблон выбранного элементаchoiceTemplate — шаблон элемента спискаgroupTemplate — шаблон группы опцийnoResultsText,
loadingText и др.)Каждый шаблон получает объект данных и контекст экземпляра компонента, что позволяет учитывать состояние интерфейса при генерации разметки.
Выбранные значения отображаются в контейнере уже выбранных элементов.
Их структура управляется через itemTemplate.
const example = new Choices('#select', {
itemTemplate: (classNames, data) => {
return `
<div class="${classNames.item} ${data.highlighted ? classNames.highlightedState : ''}"
data-item
data-id="${data.id}"
data-value="${data.value}">
<span class="custom-label">${data.label}</span>
<button type="button" class="${classNames.button}" data-button>
×
</button>
</div>
`;
}
});
Ключевые элементы объекта data:
value — значение опцииlabel — отображаемый текстid — внутренний идентификаторdisabled — флаг недоступностиhighlighted — состояние наведения/фокусаОсобенности реализации:
choiceTemplate управляет отображением элементов
выпадающего списка. Это наиболее часто переопределяемая часть UI.
const example = new Choices('#select', {
choiceTemplate: (classNames, data) => {
return `
<div class="${classNames.item} ${classNames.itemChoice} ${data.disabled ? classNames.itemDisabled : classNames.itemSelectable}"
data-choice
data-id="${data.id}"
data-value="${data.value}"
data-select-text="Выбрать">
<span class="option-title">${data.label}</span>
${data.customProperties?.description
? `<small class="option-desc">${data.customProperties.description}</small>`
: ''}
</div>
`;
}
});
Поведение шаблона:
Расширенные данные часто передаются через
customProperties:
{
value: 'us',
label: 'United States',
customProperties: {
description: 'North America',
code: 'US'
}
}
При использовании группировки опций (optgroup)
применяется groupTemplate.
groupTemplate: (classNames, data) => {
return `
<div class="${classNames.group}">
<div class="${classNames.groupHeading}">
${data.label}
</div>
</div>
`;
}
Свойства data:
label — название группыdisabled — состояние блокировкиid — идентификатор группыГруппы часто используются для:
Choices.js содержит набор текстовых сообщений, которые отображаются в разных состояниях компонента.
noResultsText: 'Ничего не найдено'
Используется при фильтрации, если совпадений нет.
noChoicesText: 'Нет доступных вариантов'
Активируется, когда список опций пуст или отключён.
loadingText: 'Загрузка...'
Отображается при асинхронной подгрузке данных.
addItemText: (value) => {
return `Добавить "${value}"`;
}
Позволяет динамически формировать сообщение на основе ввода пользователя.
maxItemText: (maxItemCount) => {
return `Можно выбрать не более ${maxItemCount} элементов`;
}
Используется при включённом ограничении
maxItemCount.
uniqueItemText: 'Этот элемент уже выбран'
Выводится при попытке добавить уже выбранное значение.
Наиболее гибкий механизм переопределения шаблонов реализуется через
callbackOnCreateTemplates.
const choices = new Choices('#select', {
callbackOnCreateTemplates: (template) => {
return {
item: (classNames, data) => {
return template(`
<div class="${classNames.item}">
${data.label}
</div>
`);
},
choice: (classNames, data) => {
return template(`
<div class="${classNames.item} ${classNames.itemChoice}">
${data.label}
</div>
`);
}
};
}
});
Особенность данного подхода:
template()Choices.js не экранирует HTML автоматически в пользовательских шаблонах. Это создаёт важные требования:
Пример небезопасного подхода:
label: "<img src=x oner ror=alert(1)>"
Без обработки это приведёт к XSS.
Корректный подход:
function escapeHtml(str) {
return str
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
Шаблоны могут зависеть от состояния данных:
Пример:
choiceTemplate: (classNames, data) => {
const status = data.selected ? 'selected' : 'available';
return `
<div class="${classNames.item} ${status}">
${data.label}
</div>
`;
}
Choices.js позволяет внедрять произвольный HTML, включая иконки:
choiceTemplate: (classNames, data) => {
return `
<div class="${classNames.item}">
<span class="icon">${data.customProperties.icon}</span>
<span class="text">${data.label}</span>
</div>
`;
}
Применение:
Переопределённые шаблоны влияют на производительность при большом количестве элементов.
Рекомендации:
Компонентные шаблоны Choices.js образуют единую систему:
choiceTemplate — входной списокitemTemplate — выбранные элементыСовместное использование всех уровней позволяет полностью переопределить визуальную модель компонента без изменения его внутренней логики.