Событие choice

Событие choice является одним из ключевых механизмов реагирования на пользовательское взаимодействие внутри компонента выбора. Оно возникает в момент, когда пользователь выбирает элемент из выпадающего списка вариантов, но до окончательного добавления значения в состояние выбранных элементов. Это делает событие важным для промежуточной логики: валидации, модификации данных, аналитики и управления поведением интерфейса.


Момент возникновения события

choice срабатывает в процессе выбора элемента из списка предложенных вариантов. Триггером выступает клик по элементу списка или выбор через клавиатурную навигацию (Enter/Tab в зависимости от конфигурации).

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

  1. Пользователь инициирует выбор
  2. Срабатывает choice
  3. Выполняется логика обработки выбора
  4. При успешном добавлении дополнительно может сработать addItem

Таким образом, choice находится на более низком уровне абстракции по сравнению с addItem.


Структура объекта события

В большинстве реализаций Choices.js объект события передаёт данные через event.detail. Основные поля:

  • choice — объект выбранного элемента
  • value — значение выбранного элемента
  • label — отображаемый текст
  • group — группа, если используется группировка опций
  • customProperties — дополнительные свойства, если они были заданы в исходных данных

Пример структуры:

{
  detail: {
    choice: {
      id: 3,
      value: "moscow",
      label: "Moscow",
      selected: false,
      disabled: false,
      customProperties: {
        region: "EU"
      }
    }
  }
}

Регистрация обработчика

Подписка на событие осуществляется через метод addEventListener у экземпляра компонента.

const element = document.querySelector('#select');

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

element.addEventListener('choice', (event) => {
  console.log('Выбран вариант:', event.detail.choice);
});

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


Отличие от addItem

Событие choice часто путается с addItem, однако между ними существует принципиальная разница по уровню обработки:

  • choice — фиксирует факт выбора элемента из списка
  • addItem — фиксирует добавление элемента в список выбранных значений

Практическое различие

element.addEventListener('choice', (e) => {
  console.log('Выбор:', e.detail.choice.value);
});

element.addEventListener('addItem', (e) => {
  console.log('Добавлено в модель:', e.detail.value);
});

В сценариях с асинхронной валидацией choice может использоваться для проверки допустимости значения до его добавления.


Управление выбором через choice

Событие choice часто используется для вмешательства в процесс выбора. Хотя само событие обычно не отменяет действие напрямую, его можно использовать в связке с методами API компонента для изменения поведения.

Типовые сценарии:

1. Валидация перед добавлением

element.addEventListener('choice', (e) => {
  const value = e.detail.choice.value;

  if (value === 'restricted') {
    console.warn('Выбор запрещён');
    choices.removeActiveItems();
  }
});

2. Подмена выбранного значения

element.addEventListener('choice', (e) => {
  if (e.detail.choice.value === 'usa') {
    choices.setChoiceByValue('united_states');
  }
});

3. Логирование пользовательских действий

element.addEventListener('choice', (e) => {
  sendAnalytics({
    event: 'choice_selected',
    value: e.detail.choice.value,
    label: e.detail.choice.label
  });
});

Поведение при разных типах выбора

Одиночный выбор

В режиме single select событие choice срабатывает при каждом изменении выбранного значения. Предыдущее значение заменяется новым, что делает событие эквивалентом переключения состояния.

Множественный выбор

В режиме multiple событие срабатывает при добавлении каждого нового элемента. При этом последовательность событий может быть следующей:

  • choice → фиксирует выбранный элемент
  • addItem → добавляет его в коллекцию

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

При включённом поиске (searchEnabled: true) событие choice тесно связано с фильтрацией списка. Выбор может происходить из отфильтрованного набора, и событие всегда содержит уже нормализованный объект выбора, независимо от исходного набора данных.


Особенности работы с группами

При использовании группированных опций (optgroup) событие choice дополнительно может содержать информацию о группе:

{
  group: {
    id: 1,
    label: "Countries"
  }
}

Это позволяет строить контекстно-зависимую логику, например ограничивать выбор внутри группы или учитывать категориальные различия.


Ограничения и нюансы

  • Событие не предназначено для прямой отмены выбора
  • Может срабатывать до обновления DOM-состояния
  • В некоторых конфигурациях порядок choice и addItem может отличаться
  • Не гарантирует финальное сохранение значения, особенно при кастомных валидаторах

Типовые архитектурные применения

Интеграция с формами

choice используется для предварительной обработки данных формы до отправки:

element.addEventListener('choice', (e) => {
  formState.lastChoice = e.detail.choice.value;
});

Динамическая фильтрация

element.addEventListener('choice', (e) => {
  filterResultsByCategory(e.detail.choice.value);
});

Синхронизация с внешними источниками данных

element.addEventListener('choice', async (e) => {
  const data = await fetch(`/api/info/${e.detail.choice.value}`);
  updateSidebar(data);
});

Связь с жизненным циклом компонента

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


Поведение при программных изменениях

При вызове методов API вроде setChoiceByValue событие choice может не срабатывать, поскольку оно ориентировано на пользовательское взаимодействие. Это различие важно при построении реактивных систем, где требуется разделение программных и пользовательских триггеров.


Сочетание с другими событиями

На практике choice часто используется вместе с:

  • search — для отслеживания ввода перед выбором
  • addItem — для подтверждения добавления
  • removeItem — для отслеживания удаления
  • change — для общего состояния формы

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