Механизм автодополнения в Tom Select строится вокруг поискового поля, которое фильтрует элементы массива и отображает подходящие совпадения по мере ввода текста. Базовая конфигурация включает указание поля поиска и списка значений:
new TomSelect("#select", {
options: [
{ id: 1, title: "JavaScript" },
{ id: 2, title: "TypeScript" },
{ id: 3, title: "Python" },
{ id: 4, title: "Go" }
],
labelField: "title",
valueField: "id",
searchField: "title",
create: false
});
Поиск выполняется по полю searchField, где допускается
указание массива ключей. Это позволяет расширить логику совпадений:
searchField: ["title", "description"]
Фильтрация осуществляется встроенным алгоритмом поиска, использующим нормализацию строк и сравнение подстрок. Поведение можно модифицировать через кастомные функции поиска и сортировки.
Tom Select позволяет переопределять механизм фильтрации через
score и sortField. Это используется при
необходимости изменить релевантность результатов.
new TomSelect("#select", {
options: data,
labelField: "name",
valueField: "id",
searchField: "name",
score: function(search) {
return function(item) {
const value = item.name.toLowerCase();
const query = search.toLowerCase();
return value.includes(query) ? 1 : 0;
};
}
});
Функция score возвращает числовую оценку релевантности.
Чем выше значение, тем выше позиция элемента в списке.
Сортировка дополняет механизм ранжирования:
sortField: {
field: "name",
direction: "asc"
}
Для динамической загрузки данных используется опция
load. Она активируется при вводе текста и позволяет
получать подсказки с сервера.
new TomSelect("#select", {
valueField: "id",
labelField: "title",
searchField: "title",
load: function(query, callback) {
if (!query.length) return callback();
fetch(`/api/search?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(json => callback(json))
.catch(() => callback());
}
});
Запрос выполняется только при наличии текста, что снижает нагрузку на сервер. Результат передаётся через callback, который обновляет список опций.
При частых запросах к API используется кэширование, позволяющее избегать повторных запросов:
const cache = {};
new TomSelect("#select", {
load: function(query, callback) {
if (cache[query]) {
callback(cache[query]);
return;
}
fetch(`/api/search?q=${query}`)
.then(res => res.json())
.then(data => {
cache[query] = data;
callback(data);
})
.catch(() => callback());
}
});
Кэш хранит результаты по ключу запроса, что уменьшает задержки при повторном вводе одинаковых символов.
Отображение элементов списка управляется через шаблоны
render. Это позволяет кастомизировать внешний вид
автокомплита.
new TomSelect("#select", {
labelField: "title",
valueField: "id",
searchField: "title",
render: {
option: function(data, escape) {
return `
<div>
<span class="title">${escape(data.title)}</span>
<span class="meta">${escape(data.category)}</span>
</div>
`;
},
item: function(data, escape) {
return `<div>${escape(data.title)}</div>`;
}
}
});
Функция escape применяется для защиты от внедрения
HTML-кода. Разделение option и item позволяет
отдельно контролировать список подсказок и выбранные значения.
Подсветка введённого текста реализуется вручную через обработку строки запроса:
render: {
option: function(data, escape) {
const query = this.inputValue || "";
const regex = new RegExp(query, "i");
const highlighted = data.title.replace(regex, function(match) {
return `<strong>${match}</strong>`;
});
return `<div>${highlighted}</div>`;
}
}
Подход зависит от текущего значения input, которое доступно через внутреннее состояние компонента.
Tom Select предоставляет набор событий, позволяющих контролировать поведение автокомплита:
new TomSelect("#select", {
onType: function(str) {
console.log("Ввод:", str);
},
onSearch: function(query) {
console.log("Поиск:", query);
},
onDropdownOpen: function() {
console.log("Список открыт");
}
});
Событие onType вызывается при каждом изменении поля
ввода. Это позволяет реализовать внешние фильтры или аналитику
ввода.
При работе с удалёнными источниками данных применяется задержка между запросами:
function debounce(fn, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn.apply(this, args), delay);
};
}
const loadData = debounce(function(query, callback) {
fetch(`/api?q=${query}`)
.then(r => r.json())
.then(callback);
}, 300);
Интеграция с Tom Select:
new TomSelect("#select", {
load: loadData
});
Задержка предотвращает отправку запроса на каждый символ и снижает нагрузку на сервер.
Для оптимизации интерфейса используется ограничение количества отображаемых элементов:
new TomSelect("#select", {
maxOptions: 10
});
Это особенно важно при больших наборах данных, где количество совпадений может быть высоким.
Функция create позволяет добавлять новые значения, если
совпадений не найдено:
new TomSelect("#select", {
create: true,
createFilter: function(input) {
return input.length > 2;
}
});
Добавление пользовательских элементов расширяет сценарии использования автокомплита до режима гибридного ввода и выбора.
Для сложных структур данных применяется переопределение фильтрации
через filter:
new TomSelect("#select", {
filter: function(item, query) {
return item.title.toLowerCase().startsWith(query.toLowerCase());
}
});
Такая логика позволяет реализовать строгий префиксный поиск, игнорируя стандартное поведение подстрочного совпадения.
Выбранные элементы доступны через API экземпляра:
const control = new TomSelect("#select");
control.setValue(2);
control.addOption({ id: 5, title: "Rust" });
control.refreshOptions();
Изменение состояния напрямую влияет на отображение автокомплита и список доступных подсказок.
При значительном объёме данных используется комбинация серверной фильтрации и минимального локального кэширования. Основной принцип заключается в передаче ответственности поиска на сервер и получении уже отфильтрованных результатов.
new TomSelect("#select", {
loadThrottle: 300,
firstUrl: function(query) {
return `/api/search?q=${encodeURIComponent(query)}`;
}
});
Подобный подход уменьшает объём передаваемых данных и ускоряет отклик интерфейса за счёт сокращения локальных вычислений.