Выбор по индексу

Работа с индексами в Choices.js требует понимания внутренней структуры хранилища данных библиотеки и способов маппинга визуального порядка элементов к их фактическим значениям. Несмотря на то что публичный API ориентирован на работу с value, часто возникает необходимость выбирать элемент именно по позиции в списке, особенно при динамическом формировании опций или синхронизации с внешними таблицами данных.

Каждый экземпляр Choices.js хранит состояние внутри внутреннего стора, где список доступных опций представлен массивом объектов. Эти объекты содержат как минимум следующие поля:

  • value — значение, используемое для формы
  • label — отображаемый текст
  • selected — состояние выбора
  • disabled — доступность элемента

Доступ к этому массиву осуществляется через внутреннее свойство экземпляра:

const choices = new Choices('#select');

const store = choices._store;
const items = store.choices;

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

Получение значения по индексу

Индексное обращение всегда опирается на стандартный массив JavaScript. После получения списка опций можно обратиться к нужному элементу напрямую:

const index = 2;
const value = choices._store.choices[index].value;

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

Важно учитывать, что порядок может изменяться при:

  • сортировке (sorter)
  • поиске (searchResultLimit, fuse.js фильтрация)
  • динамическом добавлении элементов

Поэтому индекс всегда следует воспринимать как текущую позицию в отображаемом списке, а не как фиксированную сущность.

Установка выбора по индексу

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

const choices = new Choices('#select');

function selectByIndex(index) {
  const items = choices._store.choices;

  if (!items[index]) return;

  const value = items[index].value;
  choices.setChoiceByValue(value);
}

Такой подход сохраняет совместимость с внутренней моделью библиотеки и исключает нарушение состояния.

Множественный выбор по массиву индексов

При режиме multiple возникает необходимость выбирать несколько элементов одновременно. В этом случае преобразование индексов в значения выполняется через map.

const choices = new Choices('#select-multiple');

function selectByIndexes(indexes) {
  const items = choices._store.choices;

  const values = indexes
    .map(i => items[i])
    .filter(Boolean)
    .map(item => item.value);

  choices.setChoiceByValue(values);
}

Метод setChoiceByValue принимает массив значений, что позволяет устанавливать состояние выбора за одну операцию.

Защита от некорректных индексов

Работа с индексами требует обязательной проверки границ массива. В противном случае возможны ошибки обращения к undefined:

function safeSelectByIndex(index) {
  const items = choices._store.choices;

  if (typeof index !== 'number') return;
  if (index < 0 || index >= items.length) return;

  const value = items[index].value;
  choices.setChoiceByValue(value);
}

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

Индексы и фильтрация списка

При активном поиске список choices._store.choices может не совпадать с визуально отображаемыми результатами. В этом случае индекс относится уже к отфильтрованному массиву.

const filtered = choices._store.choices.filter(c => !c.disabled);
const value = filtered[index].value;
choices.setChoiceByValue(value);

Фильтрация позволяет учитывать только доступные элементы и исключать disabled-значения из логики выбора.

Работа с активными элементами и индексной синхронизацией

При мультивыборе Choices.js хранит активные элементы отдельно от общего списка. Это позволяет реализовать синхронизацию индексов с текущим состоянием:

const activeValues = choices.getValue(true);

const activeIndexes = activeValues.map(val => {
  return choices._store.choices.findIndex(c => c.value === val);
});

Такой подход используется для построения UI-индикаторов, где требуется отображение выбранных элементов в терминах их позиций.

Изменение выбора через setChoiceByValue как основной паттерн

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

const index = 0;
const value = choices._store.choices[index].value;

choices.setChoiceByValue(value);

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

Индексы при программном добавлении опций

При добавлении новых элементов через setChoices или addChoice порядок может быть изменён. Поэтому индексная логика должна выполняться после завершения обновления стора:

choices.setChoices([
  { value: 'a', label: 'A' },
  { value: 'b', label: 'B' },
  { value: 'c', label: 'C' }
]);

const value = choices._store.choices[1].value;
choices.setChoiceByValue(value);

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

Индекс как инструмент интеграции с внешними данными

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

fetch('/api/items')
  .then(res => res.json())
  .then(data => {
    choices.setChoices(data);

    const externalIndex = 3;
    const value = choices._store.choices[externalIndex].value;

    choices.setChoiceByValue(value);
  });

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

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

Индексный выбор в Choices.js всегда зависит от текущего состояния списка. Это означает:

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

Поэтому индекс не является стабильным идентификатором элемента и должен использоваться только как временная координата внутри текущего состояния UI.