Сортировка в интерфейсе выбора играет ключевую роль в восприятии данных пользователем, особенно когда список опций становится длинным или формируется динамически. В Choices.js управление порядком элементов разделяется на две независимые области: сортировка доступных опций и порядок уже выбранных элементов. Эти механизмы настраиваются отдельно и влияют на разные части UI.
Внутренне библиотека оперирует двумя коллекциями:
Каждая из этих коллекций может иметь собственную стратегию сортировки, что позволяет гибко управлять UX.
Для управления порядком доступных значений используется параметр:
shouldSort: true
Он определяет, будут ли опции упорядочены автоматически при отображении.
Для выбранных элементов используется отдельный механизм:
shouldSortItems: false
Этот параметр отвечает за то, будет ли изменяться порядок уже выбранных значений.
Когда shouldSort включён, Choices.js сортирует список
доступных опций при каждом обновлении данных или инициализации
компонента.
По умолчанию сортировка лексикографическая, основанная на строковом сравнении меток (label). Это поведение подходит для простых списков, например стран, городов, категорий.
const choices = new Choices('#select', {
shouldSort: true
});
Однако стандартная сортировка часто оказывается недостаточной при работе с локализованными данными или числовыми значениями, записанными как строки.
Для тонкой настройки порядка элементов используется функция
сравнения. В Choices.js она может быть передана через
sortFn (или аналогичный comparator в зависимости от
версии).
Принцип работы аналогичен стандартному
Array.prototype.sort:
const choices = new Choices('#select', {
shouldSort: true,
sortFn: function(a, b) {
return a.label.localeCompare(b.label, 'ru');
}
});
Использование localeCompare позволяет учитывать языковые
особенности, что особенно важно для кириллицы.
Более сложный пример включает приоритетизацию:
sortFn: (a, b) => {
if (a.customProperties?.priority && !b.customProperties?.priority) {
return -1;
}
if (!a.customProperties?.priority && b.customProperties?.priority) {
return 1;
}
return a.label.localeCompare(b.label, 'ru');
}
В этом случае элементы с флагом priority всегда
оказываются выше остальных.
Выбранные значения отображаются в виде тегов (chips). Их порядок управляется независимо от dropdown-списка.
shouldSortItems: true
Если этот параметр включён, Choices.js автоматически сортирует выбранные элементы по алфавиту или по внутреннему правилу сортировки.
Если выключен — порядок сохраняется в том виде, в котором пользователь добавлял элементы.
const choices = new Choices('#select', {
shouldSortItems: false
});
Это поведение критично для сценариев, где важна последовательность выбора, например:
При shouldSortItems: false библиотека сохраняет
FIFO-логику (first in — first out). Последний добавленный элемент всегда
отображается последним.
При shouldSortItems: true порядок переопределяется сразу
после каждого изменения состояния, что может визуально “перемещать” уже
выбранные элементы.
Начиная с расширенных конфигураций Choices.js, порядок выбранных элементов может быть дополнительно контролируем через пользовательскую логику, используя обработку событий и программное управление состоянием.
Пример внешнего управления:
const choices = new Choices('#select', {
shouldSortItems: false
});
choices.passedElement.element.addEventListener('addItem', () => {
const items = choices.getValue();
const sorted = items.sort((a, b) => {
return a.label.length - b.label.length;
});
choices.clearStore();
choices.setValue(sorted);
});
В этом случае сортировка реализуется вручную, вне встроенного механизма.
Обе настройки независимы, но их комбинация влияет на итоговый UX.
| shouldSort | shouldSortItems | Поведение |
|---|---|---|
| true | false | опции отсортированы, выбранные в порядке добавления |
| true | true | оба списка отсортированы автоматически |
| false | false | полный контроль порядка вручную |
| false | true | выбранные сортируются, опции сохраняют исходный порядок |
Такое разделение позволяет строить как строго структурированные интерфейсы, так и полностью свободные системы выбора.
При работе с многоязычными интерфейсами важно учитывать нестабильность стандартной сортировки JavaScript. Простое сравнение строк может давать неожиданные результаты при наличии диакритики, разных алфавитов или смешанных языков.
Рекомендуемый подход:
sortFn: (a, b) => {
return a.label.localeCompare(b.label, ['ru', 'en'], {
sensitivity: 'base'
});
}
Это обеспечивает предсказуемый порядок вне зависимости от регистра и диакритических знаков.
Если значения содержат числа, записанные строками, стандартная сортировка приводит к лексикографическому порядку:
1, 10, 2, 20
Для корректного результата применяется преобразование:
sortFn: (a, b) => {
return Number(a.value) - Number(b.value);
}
Или более универсальный вариант:
sortFn: (a, b) => {
return parseInt(a.label, 10) - parseInt(b.label, 10);
}
В сценариях, где данные поступают асинхронно (например, через API), сортировка может применяться после загрузки:
fetch('/api/options')
.then(res => res.json())
.then(data => {
choices.setChoices(data, 'value', 'label', true);
});
Параметр true в setChoices может
инициировать перезапись и потенциально вызвать повторную сортировку,
если shouldSort активен.
Одной из распространённых ошибок является конфликт между:
В таких случаях итоговый порядок может отличаться от ожидаемого, поскольку библиотека применяет сортировку после каждого обновления состояния.
Другой частый случай — потеря порядка выбранных элементов при обновлении списка опций. Это происходит при повторной инициализации или очистке store:
choices.clearStore();
После этого состояние выбора сбрасывается, и порядок необходимо восстанавливать вручную.
При больших объёмах данных (тысячи элементов) сортировка становится заметной операцией. Особенно при включённых обоих параметрах сортировки.
Оптимизация достигается за счёт:
shouldSort при статичных наборах;setChoices и
setValue.В высоконагруженных интерфейсах предпочтительнее централизованная сортировка на уровне данных, а не на уровне UI-компонента.
Поиск внутри Choices.js влияет только на отображаемый subset опций.
При включённом shouldSort результат поиска также
сортируется заново, что может менять визуальный порядок совпадений.
Это особенно заметно при поиске по частичным совпадениям, когда релевантность не учитывается, а применяется только алфавитный порядок.
Для сохранения релевантности сортировку лучше отключать:
shouldSort: false
и полагаться на порядок, возвращаемый сервером или алгоритмом поиска.