Поиск в библиотеке Choices.js предназначен для быстрого нахождения
элементов внутри списка <select> или набора
пользовательских значений. По умолчанию библиотека автоматически
фильтрует варианты по введённому тексту, однако механизм поиска можно
гибко настраивать.
Алгоритм поиска влияет на:
Поиск активируется автоматически для большинства элементов, однако
его можно явно включить через параметр searchEnabled.
const choices = new Choices('#countries', {
searchEnabled: true
});
Если установить false, поле поиска исчезнет.
const choices = new Choices('#countries', {
searchEnabled: false
});
Это особенно полезно:
Параметр searchFloor задаёт минимальное число символов,
после которого начинается поиск.
const choices = new Choices('#cities', {
searchFloor: 3
});
Поведение:
| Введено | Поиск |
|---|---|
a |
нет |
ab |
нет |
abc |
да |
Такой подход снижает:
Особенно полезно при работе с тысячами элементов.
Параметр searchResultLimit задаёт максимальное число
отображаемых совпадений.
const choices = new Choices('#users', {
searchResultLimit: 10
});
Если найдено 500 совпадений, интерфейс покажет только первые 10.
Преимущества:
Choices.js поддерживает поиск не только по label, но и
по дополнительным полям объекта.
Пример данных:
const data = [
{
value: '1',
label: 'JavaScript',
customProperties: {
category: 'Frontend',
level: 'Advanced'
}
},
{
value: '2',
label: 'PHP',
customProperties: {
category: 'Backend',
level: 'Intermediate'
}
}
];
Настройка поиска:
const choices = new Choices('#skills', {
choices: data,
searchFields: [
'label',
'value',
'customProperties.category',
'customProperties.level'
]
});
Теперь поиск будет учитывать:
searchFieldsПараметр searchFields является центральным механизмом
настройки алгоритма поиска.
Пример:
searchFields: ['label']
Поиск только по отображаемому тексту.
searchFields: ['value']
Полезно при:
searchFields: [
'label',
'customProperties.description',
'customProperties.tags'
]
Такой подход превращает Choices.js в полноценный клиентский поисковый интерфейс.
Параметр searchChoices управляет самим поиском, но
регистр контролируется внутренним алгоритмом библиотеки.
По умолчанию поиск нечувствителен к регистру.
JavaScript
javascript
JAVASCRIPT
Все варианты будут найдены одинаково.
Это реализуется внутренним преобразованием строк в нижний регистр.
Стандартный алгоритм Choices.js использует поиск по вхождению строки.
Пример:
| Значение | Запрос | Совпадение |
|---|---|---|
JavaScript |
script |
да |
TypeScript |
script |
да |
Python |
script |
нет |
Такой механизм удобен для:
Параметр shouldSort отвечает за сортировку
элементов.
const choices = new Choices('#languages', {
shouldSort: true
});
По умолчанию библиотека сортирует результаты алфавитно.
const choices = new Choices('#languages', {
shouldSort: false
});
Это важно, если:
Choices.js позволяет полностью переопределить алгоритм сортировки.
const choices = new Choices('#products', {
sorter: function(a, b) {
return b.score - a.score;
}
});
Пример сортировки по рейтингу:
const choices = new Choices('#products', {
sorter: (a, b) => {
return b.customProperties.rating - a.customProperties.rating;
}
});
Для сложных сценариев часто подключается Fuse.js.
Fuse.js предоставляет:
Пример интеграции:
const fuse = new Fuse(data, {
keys: ['label', 'customProperties.description'],
threshold: 0.3
});
input.addEventListener('input', (e) => {
const results = fuse.search(e.target.value);
choices.clearChoices();
choices.setChoices(
results.map(item => item.item),
'value',
'label',
true
);
});
Нечёткий поиск позволяет находить значения даже с опечатками.
Пример:
| Запрос | Совпадение |
|---|---|
javscrit |
JavaScript |
pyton |
Python |
reasct |
React |
Стандартный поиск Choices.js этого не поддерживает, поэтому используются внешние библиотеки.
При работе с большими массивами данных производительность становится критически важной.
Если список содержит тысячи записей:
searchResultLimit: 20
searchFloor: 3
Позволяет избежать фильтрации при коротких запросах.
Вместо хранения 50 000 элементов в браузере:
input.addEventListener('search', async (event) => {
const query = event.detail.value;
const response = await fetch(`/api/search?q=${query}`);
const data = await response.json();
choices.clearChoices();
choices.setChoices(data, 'value', 'label', true);
});
Такой подход уменьшает:
Choices.js можно использовать как оболочку над серверным API.
Пример:
const choices = new Choices('#users');
document.querySelector('#users')
.addEventListener('search', async (event) => {
const value = event.detail.value;
if (value.length < 2) {
return;
}
const response = await fetch(`/users?q=${value}`);
const users = await response.json();
choices.clearChoices();
choices.setChoices(users, 'id', 'name', true);
});
Преимущества серверного поиска:
При поиске через API необходимо ограничивать количество запросов.
Пример debounce:
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
Использование:
const searchHandler = debounce(async (event) => {
const query = event.detail.value;
const response = await fetch(`/search?q=${query}`);
const data = await response.json();
choices.clearChoices();
choices.setChoices(data, 'value', 'label', true);
}, 300);
element.addEventListener('search', searchHandler);
Иногда требуется полностью заменить стандартный поиск.
Пример:
const items = [
'JavaScript',
'TypeScript',
'Python',
'PHP'
];
function customSearch(query) {
return items.filter(item => {
return item.startsWith(query);
});
}
Поиск только по началу строки:
console.log(customSearch('Py'));
Результат:
['Python']
Часто требуется ранжировать результаты.
Пример:
function rankResults(query, items) {
return items.sort((a, b) => {
const aStarts = a.label.startsWith(query);
const bStarts = b.label.startsWith(query);
if (aStarts && !bStarts) {
return -1;
}
if (!aStarts && bStarts) {
return 1;
}
return 0;
});
}
Теперь элементы, начинающиеся с введённой строки, будут выше остальных.
Choices.js генерирует событие search.
Пример:
element.addEventListener('search', (event) => {
console.log(event.detail.value);
});
Структура события:
{
value: 'jav'
}
Это позволяет:
После изменения источника данных полезно очищать старые результаты.
choices.clearChoices();
Полная перезагрузка:
choices.clearStore();
Разница:
| Метод | Что очищает |
|---|---|
clearChoices() |
список вариантов |
clearStore() |
внутреннее состояние полностью |
При использовании removeItemButton и режима
множественного выбора поиск работает и по выбранным элементам.
const choices = new Choices('#tags', {
removeItemButton: true
});
Это удобно для:
Choices.js хорошо сочетается с асинхронными источниками данных.
Пример:
async function loadUsers(query) {
const response = await fetch(`/api/users?q=${query}`);
return await response.json();
}
Интеграция:
element.addEventListener('search', async (event) => {
const query = event.detail.value;
const users = await loadUsers(query);
choices.clearChoices();
choices.setChoices(users, 'id', 'name', true);
});
Параметр noResultsText задаёт сообщение при отсутствии
совпадений.
const choices = new Choices('#users', {
noResultsText: 'Ничего не найдено'
});
Choices.js поддерживает настройку всех текстов интерфейса.
Пример:
const choices = new Choices('#countries', {
searchPlaceholderValue: 'Поиск страны',
noResultsText: 'Совпадений нет',
noChoicesText: 'Список пуст'
});
Для массивов свыше 10 000 элементов рекомендуется:
searchFloor.customProperties.Причины:
searchFields;searchEnabled;Проверка:
console.log(choices._store);
Причины:
Причина часто связана с:
shouldSort: true
или пользовательским sorter.
Крупные приложения часто объединяют:
Пример архитектуры:
search
→ debounce
→ API
→ Fuse.js
→ сортировка
→ setChoices()
Такой подход позволяет создавать: