Событие beforeChange перехватывает момент до применения
нового значения в компоненте Slim Select и позволяет вмешаться в процесс
обновления выбранных данных. Это ключевая точка управления состоянием,
когда ещё возможно отменить изменение, проверить его корректность или
модифицировать входящие данные до их фиксации в DOM и внутреннем
состоянии экземпляра.
В Slim Select изменение значения проходит несколько последовательных этапов:
beforeChangeafterChangebeforeChange располагается строго перед фиксацией нового
состояния и является единственной точкой, где изменение можно остановить
до того, как оно станет фактическим значением селекта.
Обработчик beforeChange обычно получает контекст
текущего экземпляра Slim Select и информацию о предполагаемом
изменении:
new SlimSelect({
select: '#select',
events: {
beforeChange: (newValue, oldValue, slim) => {
// логика обработки
}
}
});
Типовая структура параметров:
newValue — значение, которое планируется
установитьoldValue — текущее значение до измененияslim — экземпляр Slim Select, позволяющий обращаться к
API компонентаВ некоторых реализациях параметры могут быть сгруппированы в объект, но логика остаётся аналогичной: предоставляется доступ к текущему и новому состоянию.
Основная функциональность beforeChange заключается в
возможности отменить обновление. Для этого обработчик должен вернуть
false.
beforeChange: (newValue, oldValue, slim) => {
if (newValue.includes('forbidden')) {
return false;
}
}
При возврате false:
afterChange не вызываетсяЛюбое другое возвращаемое значение (или отсутствие
return) означает разрешение изменения.
Через slim доступен полный API экземпляра Slim Select,
включая:
slim.getSelected())set,
enable, disable)Это позволяет строить сложную логику контроля выбора:
beforeChange: (newValue, oldValue, slim) => {
const selected = slim.getSelected();
if (selected.length > 3) {
return false;
}
}
Событие часто используется для реализации ограничений, которые невозможно выразить через HTML-атрибуты:
beforeChange: (newValue, oldValue, slim) => {
if (Array.isArray(newValue) && newValue.length > 5) {
return false;
}
}
Такой подход применяется в мультиселектах, где требуется контроль максимального количества выбранных элементов.
const blocked = ['admin', 'root', 'system'];
beforeChange: (newValue) => {
if (blocked.includes(newValue)) {
return false;
}
}
Подобная логика используется для предотвращения выбора служебных или недопустимых опций.
beforeChange: (newValue, oldValue, slim) => {
const current = slim.getSelected();
if (current.includes('locked') && newValue !== 'unlock') {
return false;
}
}
В ряде сценариев требуется не отмена, а коррекция данных до
применения. Хотя beforeChange в Slim Select в первую
очередь предназначен для валидации, некоторые версии допускают возврат
изменённого значения.
beforeChange: (newValue) => {
if (typeof newValue === 'string') {
return newValue.trim().toLowerCase();
}
}
При этом важно учитывать, что подобное поведение зависит от версии библиотеки и не всегда гарантировано как официально поддерживаемое.
Прямой асинхронный beforeChange в большинстве реализаций
Slim Select не поддерживается. Однако возможен обходной паттерн с
предварительной блокировкой изменения и внешней проверкой:
let isValidating = false;
beforeChange: (newValue) => {
if (isValidating) return false;
isValidating = true;
fakeApiCheck(newValue).then(result => {
isValidating = false;
if (result.valid) {
slim.set(result.value);
}
});
return false;
}
В такой схеме изменение всегда блокируется до завершения внешней проверки, а затем применяется вручную.
afterChangebeforeChange тесно связан с последующим событием
afterChange. Логика разделяется следующим образом:
beforeChange — контроль и фильтрацияafterChange — реакция на уже применённое состояниеevents: {
beforeChange: (newValue) => {
if (!newValue) return false;
},
afterChange: (newValue) => {
console.log('значение изменено:', newValue);
}
}
Важно учитывать, что afterChange не срабатывает при
отмене в beforeChange.
beforeChangeИзменение состояния селекта внутри beforeChange без
контроля может привести к циклическим вызовам:
beforeChange: (newValue, oldValue, slim) => {
slim.set('value'); // риск рекурсии
}
Отсутствие явного return false часто приводит к тому,
что разработчики ожидают блокировки, но изменение всё равно
применяется.
beforeChange: () => {
if (true) {
false; // не блокирует изменение
}
}
В мультиселектах newValue может быть массивом, и
проверка должна учитывать это:
beforeChange: (newValue) => {
if (Array.isArray(newValue) && newValue.includes('invalid')) {
return false;
}
}
beforeChange часто используется как центральный узел
бизнес-логики формы:
beforeChange: (newValue, oldValue, slim) => {
const userRole = getUserRole();
if (userRole !== 'admin' && newValue === 'admin-mode') {
return false;
}
if (newValue === 'reset') {
slim.set([]);
return false;
}
}
Такая структура позволяет управлять поведением компонента без изменения его внутренней логики и без вмешательства в DOM напрямую.