Интеграция с jQuery

Choices.js изначально не зависит от jQuery и построен на нативном DOM API. При интеграции с jQuery возникает слой адаптации, в котором jQuery выступает как средство выбора элементов, управления коллекциями и организации жизненного цикла компонентов, а Choices.js — как независимый UI-рендеринг поверх <select> или <input>.

Ключевая особенность интеграции заключается в том, что экземпляр Choices привязывается к DOM-элементу один раз, после чего управление состоянием должно происходить либо через API Choices, либо через аккуратное обновление DOM с последующим вызовом методов обновления.


Базовая инициализация через jQuery-обертку

Наиболее распространённый сценарий — инициализация Choices на элементах, полученных через jQuery-селектор.

$(document).ready(function () {
  const $select = $('#country-select');

  const choicesInstance = new Choices($select[0], {
    searchEnabled: true,
    removeItemButton: true,
    shouldSort: false
  });
});

Ключевой момент

jQuery возвращает коллекцию, а Choices требует чистый DOM-элемент, поэтому используется индекс [0].


Инициализация на множестве элементов

При работе с формами, содержащими несколько <select> или <input>, используется итерация по jQuery-коллекции.

$('.js-choices').each(function () {
  const element = this;

  const instance = new Choices(element, {
    searchEnabled: true,
    itemSelectText: ''
  });

  $(element).data('choices-instance', instance);
});

Особенности хранения экземпляра

Использование $.data() позволяет:

  • сохранять ссылку на экземпляр
  • повторно использовать API Choices
  • управлять уничтожением инстанса

Управление жизненным циклом (инициализация и уничтожение)

Choices.js не рассчитан на повторную инициализацию поверх уже существующего экземпляра без его уничтожения.

function initChoices($el) {
  const existing = $el.data('choices-instance');

  if (existing) {
    existing.destroy();
  }

  const instance = new Choices($el[0], {
    searchEnabled: true
  });

  $el.data('choices-instance', instance);
}

Типичный сценарий применения

  • динамическая перерисовка форм
  • модальные окна, создаваемые повторно
  • AJAX-обновление DOM

Интеграция с динамическими DOM-обновлениями jQuery

При вставке новых элементов через jQuery (.html(), .append(), .load()) Choices не активируется автоматически. Требуется повторная инициализация.

$('#container').html(newContent);

$('#container').find('select.js-choices').each(function () {
  new Choices(this, {
    searchEnabled: true
  });
});

Важный нюанс

Choices хранит внутреннее состояние, поэтому повторная инициализация без destroy приводит к:

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

Работа с событиями через jQuery-экосистему

Choices генерирует собственные события (addItem, removeItem, change). Их можно синхронизировать с jQuery-логикой.

const $el = $('#tags');

const instance = new Choices($el[0]);

$el.on('addItem', function (event) {
  console.log('Добавлен элемент:', event.detail.value);
});

$el.on('removeItem', function (event) {
  console.log('Удалён элемент:', event.detail.value);
});

Расширенный вариант через нативные события

Choices диспатчит события на DOM-элемент, поэтому jQuery корректно их перехватывает без дополнительных адаптеров.


Интеграция с AJAX-загрузкой данных (jQuery.ajax)

Choices не имеет встроенной зависимости от jQuery.ajax, но легко комбинируется с ней при заполнении списка.

const $select = $('#users');

const instance = new Choices($select[0], {
  searchEnabled: true
});

$.ajax({
  url: '/api/users',
  method: 'GET',
  success: function (data) {
    const items = data.map(user => ({
      value: user.id,
      label: user.name
    }));

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

Поведение setChoices

  • третий параметр true очищает старые значения
  • позволяет полностью заменить список опций

Делегирование и работа с динамическими селекторами

При использовании динамически создаваемых элементов jQuery делегирование применяется только к моменту инициализации, но не к самому Choices.

$(document).on('focus', 'select.js-choices', function () {
  if (!$(this).data('choices-instance')) {
    const instance = new Choices(this);
    $(this).data('choices-instance', instance);
  }
});

Ограничение подхода

Инициализация по событию focus может приводить к задержке UX, поэтому чаще используется явный init после вставки DOM.


Синхронизация состояния jQuery и Choices

Choices управляет состоянием независимо от jQuery .val(). Прямое изменение значения через jQuery не всегда отражается в UI.

Корректный способ обновления значения

const $select = $('#status');
const instance = $select.data('choices-instance');

instance.setChoiceByValue('active');

Некорректный способ

$('#status').val('active'); // UI Choices не обновится

Удаление и полная очистка экземпляра

При работе SPA-подобных интерфейсов требуется корректное уничтожение инстанса.

function destroyChoices($el) {
  const instance = $el.data('choices-instance');

  if (instance) {
    instance.destroy();
    $el.removeData('choices-instance');
  }
}

Что делает destroy

  • удаляет DOM-обёртку Choices
  • восстанавливает оригинальный <select>
  • снимает обработчики событий

Комбинирование jQuery chaining с Choices API

Choices не поддерживает chaining jQuery напрямую, но можно сохранять семантику цепочек через возврат jQuery-объекта.

$.fn.activateChoices = function (options) {
  return this.each(function () {
    const instance = new Choices(this, options);
    $(this).data('choices-instance', instance);
  });
};

$('.js-choices').activateChoices({
  searchEnabled: true
});

Частые проблемы при интеграции

Повторная инициализация

Возникает при повторном вызове без destroy. Приводит к наложению UI.

Несовпадение состояния

jQuery .val() не синхронизирует UI Choices.

Потеря событий при перерисовке DOM

При .html() контейнера старые экземпляры теряются и требуют повторного связывания.

Конфликт динамических данных

При AJAX-обновлениях важно использовать setChoices, а не прямую модификацию <option>.


Рекомендованная модель взаимодействия

  • jQuery используется как слой DOM-манипуляций
  • Choices управляет UI и состоянием выбора
  • Связка осуществляется через сохранение instance в .data()
  • Любое изменение структуры требует явного re-init или destroy+init