Блокировка отдельных значений в Tom Select применяется для управления доступностью элементов списка без удаления данных из источника. Это используется при условной валидации, ограничениях бизнес-логики, зависимости между полями и работе с динамическими наборами опций.
Блокировка может затрагивать весь компонент целиком, отдельные элементы списка или поведение добавления значений. Внутренняя модель Tom Select позволяет комбинировать несколько уровней ограничения: через состояние компонента, через свойства опций и через перехват событий.
На уровне экземпляра Tom Select существует управление состоянием активности поля. При отключении компонент перестаёт реагировать на ввод, открытие списка и выбор элементов.
const ts = new TomSelect("#select", {
options: [
{ value: "1", text: "Alpha" },
{ value: "2", text: "Beta" }
]
});
// блокировка
ts.disable();
// разблокировка
ts.enable();
Состояние отключения влияет на:
Дополнительно состояние синхронизируется с оригинальным
<select disabled> при инициализации.
Каждый элемент списка может содержать флаг, запрещающий выбор. Tom Select учитывает его при рендеринге и при попытке добавления элемента.
new TomSelect("#select", {
options: [
{ value: "1", text: "Разрешено" },
{ value: "2", text: "Недоступно", disabled: true },
{ value: "3", text: "Разрешено" }
],
render: {
option: function(data, escape) {
return `
<div class="${data.disabled ? 'disabled' : ''}">
${escape(data.text)}
</div>
`;
}
}
});
Особенности поведения:
В реальных сценариях состояние доступности часто меняется после загрузки данных или действий пользователя. Tom Select позволяет модифицировать опции после инициализации.
const ts = new TomSelect("#select", { options: [] });
ts.addOption({ value: "1", text: "A" });
ts.addOption({ value: "2", text: "B" });
// обновление опции
ts.updateOption("2", {
value: "2",
text: "B",
disabled: true
});
Если требуется массовая блокировка:
ts.getOption("1").classList.add("disabled");
ts.refreshOptions(false);
Внутренний механизм не всегда автоматически запрещает выбор при кастомной DOM-модификации, поэтому логика должна дублироваться на уровне событий.
Одним из наиболее надёжных способов блокировки является контроль события добавления значения. Даже если опция отображается как доступная, её можно отклонить на уровне логики.
new TomSelect("#select", {
onItemAdd: function(value, item) {
if (value === "2") {
this.removeItem(value);
}
}
});
Такой подход применяется, когда:
При работе с удалёнными данными можно полностью исключить загрузку неподходящих значений.
new TomSelect("#select", {
load: function(query, callback) {
fetch(`/api/items?q=${query}`)
.then(res => res.json())
.then(data => {
const filtered = data.filter(item => !item.locked);
callback(filtered);
});
}
});
Фильтрация на этапе загрузки предотвращает появление заблокированных элементов в интерфейсе.
Часто используется расширение модели опции дополнительными атрибутами.
{
value: "10",
text: "Premium",
locked: true
}
Логика блокировки переносится в единый слой:
new TomSelect("#select", {
onItemAdd: function(value) {
const option = this.options[value];
if (option && option.locked) {
this.removeItem(value);
}
}
});
Такой подход упрощает интеграцию с API и серверной валидацией.
При группировке опций можно блокировать целые группы значений.
new TomSelect("#select", {
optgroups: [
{ value: "group1", label: "Доступные" },
{ value: "group2", label: "Заблокированные" }
],
options: [
{ value: "a", text: "A", optgroup: "group1" },
{ value: "b", text: "B", optgroup: "group2", disabled: true }
]
});
Это удобно при разделении:
Сам по себе механизм блокировки не всегда очевиден пользователю, поэтому важна кастомизация отображения.
render: {
option: function(data, escape) {
return `
<div class="option ${data.disabled ? 'is-disabled' : ''}">
<span>${escape(data.text)}</span>
</div>
`;
}
}
CSS-слой:
.is-disabled {
opacity: 0.4;
pointer-events: none;
}
Это усиливает семантическое соответствие между логикой и интерфейсом.
При интеграции с формами часто требуется синхронизация блокировки с другими полями.
const ts = new TomSelect("#select");
document.querySelector("#toggle").addEventListener("change", (e) => {
if (e.target.checked) {
ts.updateOption("1", { value: "1", text: "A", disabled: true });
} else {
ts.updateOption("1", { value: "1", text: "A", disabled: false });
}
});
Такая модель используется для:
Хотя это не прямая блокировка опций, ограничение количества выбранных значений влияет на доступность дальнейшего выбора.
new TomSelect("#select", {
maxItems: 1
});
После достижения лимита:
При активном поиске заблокированные элементы могут продолжать появляться в результатах. В этом случае требуется дополнительная фильтрация:
new TomSelect("#select", {
score: function(search) {
return function(item) {
return item.disabled ? 0 : 1;
};
}
});
Или полное исключение из результата:
filter: function(item) {
return !item.disabled;
}
В сложных интерфейсах применяется комбинация методов:
disabled: true для базовой блокировкиonItemAddupdateOptionТакая архитектура обеспечивает устойчивость к несогласованности данных между клиентом и сервером, а также защищает от обхода ограничений через UI.