Блокировка селекта

Работа с блокировкой селекта в Choices.js строится на двух уровнях управления: нативное состояние HTML-элемента <select> и внутреннее состояние экземпляра Choices, который управляет отрисовкой, поиском и выбором значений. Игнорирование одного из уровней приводит к рассинхронизации интерфейса: визуально компонент может оставаться активным, хотя логически уже должен быть недоступен, и наоборот.

Базовый механизм блокировки реализуется через стандартный атрибут disabled у элемента <select>.

<select id="city-select">
  <option value="1">Алматы</option>
  <option value="2">Астана</option>
  <option value="3">Шымкент</option>
</select>
const select = document.getElementById('city-select');

select.disabled = true;

После применения атрибута браузер отключает взаимодействие с элементом, однако Choices.js, если уже инициализирован, не всегда полностью отражает это состояние без дополнительного обновления.

Блокировка экземпляра Choices.js

Choices.js предоставляет собственный механизм управления доступностью через методы экземпляра.

const select = document.getElementById('city-select');

const choices = new Choices(select, {
  searchEnabled: true
});

choices.disable();

Метод disable() переводит компонент в состояние полной блокировки:

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

Разблокировка выполняется симметрично:

choices.enable();

Различие между select.disabled и choices.disable()

Эти два подхода воздействуют на разные слои системы:

  • select.disabled = true — влияет на DOM-элемент и поведение формы
  • choices.disable() — управляет UI-слоем Choices.js

При использовании только одного из методов возможны несоответствия:

  • отключён DOM, но интерфейс Choices остаётся кликабельным
  • отключён Choices, но форма всё ещё отправляет данные
  • отключён UI, но значение изменяется скриптами

Корректная блокировка часто требует синхронного применения обоих механизмов:

select.disabled = true;
choices.disable();

Динамическая блокировка в зависимости от состояния данных

Часто блокировка используется при загрузке данных или ожидании ответа сервера.

async function loadCities() {
  select.disabled = true;
  choices.disable();

  const response = await fetch('/api/cities');
  const data = await response.json();

  choices.setChoices(data, 'value', 'label', true);

  select.disabled = false;
  choices.enable();
}

Такая схема предотвращает взаимодействие пользователя с неполностью загруженным списком.

Блокировка отдельных опций

Choices.js поддерживает отключение отдельных пунктов списка через параметр disabled в данных.

const choices = new Choices(select, {
  choices: [
    { value: '1', label: 'Алматы' },
    { value: '2', label: 'Астана', disabled: true },
    { value: '3', label: 'Шымкент' }
  ]
});

Отключённая опция:

  • отображается в списке
  • недоступна для выбора
  • может быть стилизована отдельно (серый текст, отсутствие hover)

Этот подход используется при частичной доступности данных без полной блокировки компонента.

Блокировка выбора при сохранении активности UI

Иногда требуется сохранить доступ к просмотру списка, но запретить изменение выбранного значения. В Choices.js это реализуется комбинацией отключения взаимодействия и управления состоянием выбора.

choices.disable();

При необходимости более мягкого ограничения применяется отключение только поисковой строки:

const choices = new Choices(select, {
  searchEnabled: false
});

Это не блокировка в строгом смысле, но снижает возможность изменения выбора.

Управление состоянием при множественном выборе

Для select multiple блокировка действует на весь список выбранных элементов:

choices.disable();

Особенности поведения:

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

При повторной активации:

choices.enable();

состояние выбора полностью восстанавливается без потерь.

Программная блокировка через внешние условия

Часто блокировка привязывается к логике формы:

const submitBtn = document.getElementById('submit');

submitBtn.addEventListener('click', () => {
  choices.disable();
  select.disabled = true;
});

Или при валидации:

function validateForm(data) {
  if (!data.country) {
    choices.disable();
    return false;
  }

  return true;
}

Поведение при очистке и блокировке

При блокировке важно учитывать текущее значение:

choices.removeActiveItems();
choices.disable();

Если этого не сделать, выбранное значение может остаться в DOM-элементе, несмотря на визуальную блокировку интерфейса.

Частичная блокировка через состояние приложения

В сложных интерфейсах блокировка часто привязывается к состояниям:

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

Пример каскадной логики:

countryChoices.disable();
cityChoices.disable();

fetchCitiesByCountry().then(data => {
  cityChoices.setChoices(data, 'value', 'label', true);
  cityChoices.enable();
});

Поведение при повторной инициализации

При повторном создании экземпляра Choices на том же элементе необходимо учитывать предыдущее состояние блокировки:

choices.destroy();

select.disabled = true;

const newChoices = new Choices(select);

Если disabled не сброшен, новый экземпляр унаследует состояние DOM-элемента и останется неактивным.

Итоговая модель блокировки

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

  • состояние DOM (select.disabled)
  • состояние экземпляра (choices.disable())
  • состояние данных (флаг disabled у опций)

Согласованное управление этими уровнями обеспечивает предсказуемое поведение интерфейса без визуальных и логических расхождений.