Переход с альтернативных решений для кастомизации
<select>-элементов на Choices.js требует учета
различий в архитектуре, API и модели управления состоянием. Большинство
библиотек для работы с выпадающими списками делятся на две категории:
манипуляция DOM напрямую и абстракция над состоянием с внутренним
хранилищем данных. Choices.js относится ко второй группе, где DOM
является лишь представлением состояния экземпляра.
Ключевые аспекты, влияющие на миграцию:
<option> в пользу API
экземпляра;<select>Нативный <select> часто используется как базовая
реализация, поверх которой накладывается кастомизация.
<sel ect id="city">
<option value="msk">Москва</option>
<option value="spb">Санкт-Петербург</option>
<option value="ekb">Екатеринбург</option>
</select>
import Choices fr om 'choices.js';
const select = document.getElementById('city');
const choices = new Choices(select, {
searchEnabled: true,
shouldSort: false
});
Нативное управление:
select.value = 'spb';
Choices.js:
choices.setChoiceByValue('spb');
Добавление опций:
select.add(new Option('Казань', 'kzn'));
Choices.js:
choices.setChoices([
{ value: 'kzn', label: 'Казань' }
], 'value', 'label', false);
Удаление элементов полностью переносится в API экземпляра:
choices.removeActiveItems();
choices.clearChoices();
Select2 широко использует jQuery и событийную модель, что делает переход на Choices.js концептуально заметным.
$('#city').select2({
placeholder: 'Выбор города',
allowClear: true
});
const element = document.getElementById('city');
const choices = new Choices(element, {
removeItemButton: true,
placeholder: true,
placeholderValue: 'Выбор города'
});
Select2:
$('#city').on('change', function () {
console.log(this.value);
});
Choices.js:
element.addEventListener('change', (event) => {
console.log(event.target.value);
});
или через внутренние события:
choices.passedElement.element.addEventListener(
'addItem',
(event) => console.log(event.detail.value)
);
Select2 использует jQuery API для обновления данных:
$('#city').val('msk').trigger('change');
Choices.js:
choices.setChoiceByValue('msk');
Chosen является одной из ранних библиотек, ориентированных на UX
улучшение <select>.
$('#city').chosen({
no_results_text: 'Ничего не найдено'
});
const choices = new Choices('#city', {
noResultsText: 'Ничего не найдено'
});
Chosen:
<option>.Choices.js:
Обновление списка:
Chosen:
$('#city').append('<option value="kzn">Казань</option>');
$('#city').trigger('chosen:updated');
Choices.js:
choices.setChoices([
{ value: 'kzn', label: 'Казань' }
], 'value', 'label', false);
Tom Select ближе по философии к Choices.js, однако отличается более богатым API и поддержкой сложных сценариев тегирования.
new TomSelect('#city', {
create: true,
sortField: 'text'
});
const choices = new Choices('#city', {
duplicateItemsAllowed: false,
shouldSort: true
});
Tom Select:
control.addOption({ value: 'kzn', text: 'Казань' });
Choices.js:
choices.setChoices([
{ value: 'kzn', label: 'Казань', selected: false }
], 'value', 'label', false);
или при включенной опции пользовательского ввода:
const choices = new Choices('#city', {
duplicateItemsAllowed: false,
addItems: true
});
<select id="tags" multiple>
<option value="js">JavaScript</option>
<option value="css">CSS</option>
</select>
Установка значений:
document.getElementById('tags').value = ['js', 'css'];
const choices = new Choices('#tags', {
removeItemButton: true
});
choices.setChoiceByValue(['js', 'css']);
Добавление элементов:
choices.setChoiceByValue('js');
choices.setChoiceByValue('css');
или пакетно:
choices.setChoices([
{ value: 'js', label: 'JavaScript', selected: true },
{ value: 'css', label: 'CSS', selected: true }
], 'value', 'label', false);
Во многих библиотеках используется AJAX-загрузка. В Choices.js отсутствует встроенный AJAX-слой, поэтому миграция требует явного подключения логики загрузки данных.
$('#city').select2({
ajax: {
url: '/api/cities',
processResults: (data) => ({
results: data.items
})
}
});
const choices = new Choices('#city', {
searchEnabled: true
});
fetch('/api/cities')
.then(res => res.json())
.then(data => {
choices.setChoices(
data.items.map(item => ({
value: item.id,
label: item.name
})),
'value',
'label',
false
);
});
Некоторые библиотеки позволяют полностью переопределять шаблоны.
Использование template callbacks или HTML в строках.
Использование конфигурации
callbackOnCreateTemplates:
const choices = new Choices('#city', {
callbackOnCreateTemplates: function (template) {
return {
item: (classNames, data) => {
return template(`
<div class="${classNames.item} ${data.highlighted
? classNames.highlightedState
: classNames.itemSelectable}">
${data.label}
</div>
`);
}
};
}
});
Разные библиотеки используют разные уровни событийности.
| Действие | Select2 | Choices.js |
|---|---|---|
| выбор элемента | select2:select |
addItem |
| удаление | select2:unselect |
removeItem |
| открытие | select2:open |
showDropdown |
| закрытие | select2:close |
hideDropdown |
Пример обработки:
choices.passedElement.element.addEventListener('addItem', (e) => {
console.log(e.detail.value);
});
В старых библиотеках ограничения часто реализуются через DOM или внешнюю логику.
maximumSelectionLength: 3
const choices = new Choices('#tags', {
maxItemCount: 3
});
Дополнительные ограничения:
{
maxItemText: 'Максимум элементов достигнут',
duplicateItemsAllowed: false
}
Старые библиотеки часто требуют переопределения CSS через глобальные классы.
Choices.js использует собственную систему классов:
choiceschoices__innerchoices__itemchoices__listПри миграции важно:
select2-*,
chosen-*;$('#city').select2('destroy');
choices.destroy();
После уничтожения:
| Характеристика | jQuery-библиотеки | Choices.js |
|---|---|---|
| зависимость | jQuery | отсутствует |
| состояние | DOM + plugin data | внутренний state |
| обновление | через trigger | через API |
| масштабируемость | ограниченная | высокая |
| SSR-совместимость | низкая | выше |
.val() вместо API;destroy();