Отключение опций

В библиотеке Choices.js управление доступностью элементов списка строится на нескольких уровнях: исходные HTML-атрибуты, конфигурация при инициализации, а также программное API. Отключение опций (choices) означает запрет их выбора пользователем при сохранении их визуального отображения в выпадающем списке.

Ключевой принцип: disabled-состояние может быть задано как на уровне DOM, так и на уровне JavaScript-структуры данных Choices.js.


Отключение опций через HTML-разметку

Самый базовый способ — использование стандартного HTML-атрибута disabled внутри <option>:

<select id="example">
  <option value="1">Активный пункт</option>
  <option value="2" disabled>Недоступный пункт</option>
  <option value="3">Ещё один активный</option>
</select>

После инициализации Choices.js такие элементы автоматически интерпретируются как недоступные для выбора. Они:

  • отображаются в списке
  • визуально помечаются как неактивные
  • игнорируются при выборе через клавиатуру и поиск
  • не могут быть добавлены в выбранные значения

Отключение при инициализации через данные choices

При использовании JavaScript-инициализации список может задаваться вручную через параметр choices. В этом случае отключение элемента выполняется через свойство disabled.

const instance = new Choices('#example', {
  choices: [
    { value: '1', label: 'Активный пункт' },
    { value: '2', label: 'Отключённый пункт', disabled: true },
    { value: '3', label: 'Активный пункт 2' }
  ]
});

Каждый объект choice может содержать:

  • value — значение
  • label — отображаемый текст
  • disabled: true — флаг недоступности

Особенности отображения отключённых элементов

Choices.js не удаляет disabled-элементы из DOM-списка, а только изменяет их поведение:

  • элементы остаются видимыми в dropdown
  • не участвуют в поисковой выдаче (в зависимости от конфигурации поиска)
  • получают CSS-класс состояния disabled
  • игнорируются при навигации стрелками

Это важно для сохранения контекста списка, особенно при больших наборах данных.


Отключение опций через API setChoices

При динамической загрузке данных используется метод setChoices, который также поддерживает параметр disabled.

instance.setChoices([
  { value: '10', label: 'Доступно' },
  { value: '11', label: 'Недоступно', disabled: true }
], 'value', 'label', true);

Последний параметр (true) указывает на замену текущего списка.

Типичная ошибка — попытка обновить список без учёта флага disabled, что приводит к потере состояния доступности.


Динамическое управление состоянием disabled

Choices.js позволяет изменять доступность элементов после инициализации, но напрямую API для “toggle disabled” ограничен. Поэтому применяются обходные стратегии:

Полная перезагрузка списка

const updated = instance._store.choices.map(item => {
  if (item.value === '2') {
    return { ...item, disabled: true };
  }
  return item;
});

instance.setChoices(updated, 'value', 'label', true);

Этот подход используется при сложной бизнес-логике, где состояние опций зависит от внешних факторов.


Отключение выбора уже выбранных значений

Choices.js поддерживает мультивыбор, и в этом режиме важно различать:

  • выбранные элементы
  • доступные элементы

Чтобы запретить повторное добавление или ограничить выбор, используется логика отключения после выбора:

instance.passedElement.element.addEventListener('addItem', (event) => {
  const value = event.detail.value;

  const updated = instance._store.choices.map(choice => {
    if (choice.value === value) {
      return { ...choice, disabled: true };
    }
    return choice;
  });

  instance.setChoices(updated, 'value', 'label', true);
});

Такой подход часто применяется для:

  • ограничения уникальных тегов
  • предотвращения повторного выбора
  • реализации зависимых списков

Взаимодействие disabled с поиском

Поиск в Choices.js (searchEnabled) учитывает состояние опций:

  • disabled-элементы обычно исключаются из результатов
  • при кастомной реализации фильтрации может потребоваться дополнительная проверка choice.disabled

Пример логики фильтрации:

const filtered = choices.filter(choice => {
  return !choice.disabled && choice.label.includes(query);
});

Визуальное представление отключённых элементов

UI-состояние disabled в Choices.js выражается через:

  • затемнение текста
  • отсутствие hover-эффекта
  • запрет клика
  • добавление служебного CSS-класса

При кастомизации стилей важно учитывать, что библиотека не удаляет элементы из DOM, а только меняет их интерактивность.

Пример переопределения:

.choices__item--disabled {
  opacity: 0.4;
  pointer-events: none;
}

Ограничение выбора через disabled и maxItemCount

В мультиселекте часто используется комбинация:

  • maxItemCount
  • removeItemButton
  • disabled choices

Пример конфигурации:

new Choices('#example', {
  maxItemCount: 3,
  removeItemButton: true
});

При достижении лимита элементы могут программно помечаться как disabled, чтобы визуально сигнализировать невозможность дальнейшего выбора.


Состояние disabled при группах опций

Choices.js поддерживает группы (optgroup), и отключение может применяться на двух уровнях:

  • отключение всей группы
  • отключение отдельных элементов внутри группы

HTML-пример:

<select>
  <optgroup label="Группа 1" disabled>
    <option value="1">A</option>
    <option value="2">B</option>
  </optgroup>
</select>

В этом случае все дочерние элементы наследуют состояние недоступности.


Сценарии каскадного отключения

В сложных интерфейсах отключение опций часто зависит от других селектов. Пример каскадной логики:

  • выбор страны
  • загрузка городов
  • отключение городов, не относящихся к выбранной стране
countrySelect.passedElement.element.addEventListener('change', (event) => {
  const country = event.detail.value;

  fetchCities(country).then(cities => {
    citySelect.setChoices(
      cities.map(city => ({
        value: city.id,
        label: city.name,
        disabled: !city.available
      })),
      'value',
      'label',
      true
    );
  });
});

Ограничения и особенности поведения

При работе с отключёнными опциями важно учитывать архитектурные особенности Choices.js:

  • внутренний store не всегда синхронизируется при прямом изменении объектов
  • изменение disabled требует пересборки списка через setChoices
  • DOM не является единственным источником истины — используется внутренняя модель данных

Сочетание disabled с пользовательским поиском и сортировкой

При включённых настройках:

  • shouldSort
  • searchEnabled
  • кастомный fuseOptions

disabled-элементы могут:

  • оставаться в списке, но перемещаться вниз
  • полностью исключаться из выдачи
  • требовать ручной фильтрации при кастомных рендерах

Пример защиты от попадания disabled в сортировку:

const sorted = choices
  .filter(c => !c.disabled)
  .sort((a, b) => a.label.localeCompare(b.label));

Использование disabled в сценариях форм валидации

Отключение опций часто используется как часть валидации формы:

  • запрет выбора уже использованных значений
  • блокировка недоступных тарифов
  • исключение несовместимых комбинаций

Типовой подход:

  • событие изменения формы
  • пересчёт допустимых значений
  • обновление Choices через setChoices

Поведение при удалении элементов

В режиме мультиселекта удаление элемента (removeItemButton) не обязательно снимает disabled-состояние. Это зависит от логики приложения:

  • если disabled используется как “однократный выбор” — состояние сохраняется
  • если disabled используется как “занятость” — при удалении может сниматься

Пример снятия блокировки:

instance.passedElement.element.addEventListener('removeItem', (event) => {
  const value = event.detail.value;

  const updated = instance._store.choices.map(choice => {
    if (choice.value === value) {
      return { ...choice, disabled: false };
    }
    return choice;
  });

  instance.setChoices(updated, 'value', 'label', true);
});