Загрузка файлов вручную

В Choices.js управление элементами списка строится вокруг массива choices, который может заполняться как статически при инициализации, так и динамически после создания экземпляра. При работе с локальными файлами основной задачей становится преобразование внешних данных (JSON, CSV, текстовых файлов) в формат, который библиотека способна интерпретировать через методы setChoices, clearChoices, removeActiveItems и setValue.

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


Базовая структура данных Choices

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

{
  value: "unique_value",
  label: "Отображаемый текст",
  selected: false,
  disabled: false,
  customProperties: {}
}

При ручной загрузке файлов важно привести данные к этой структуре. Любой источник — JSON, CSV или текстовый файл — должен быть преобразован в массив таких объектов.


Загрузка JSON-файла через FileReader

Наиболее распространённый сценарий — загрузка JSON-файла с диска пользователя.

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

[
  { "value": "1", "label": "Москва" },
  { "value": "2", "label": "Санкт-Петербург" },
  { "value": "3", "label": "Новосибирск" }
]

Обработка файла

const fileInput = document.querySelector('#fileInput');

const choicesInstance = new Choices('#sel ect', {
  searchEnabled: true,
  shouldSort: false
});

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  if (!file) return;

  const reader = new FileReader();

  reader.onl oad = (e) => {
    try {
      const data = JSON.parse(e.target.result);

      const formatted = data.map(item => ({
        value: item.value,
        label: item.label,
        selected: false,
        disabled: false
      }));

      choicesInstance.clearChoices();
      choicesInstance.setChoices(formatted, 'value', 'label', true);
    } catch (err) {
      console.error('Ошибка парсинга JSON:', err);
    }
  };

  reader.readAsText(file);
});

Пакетная загрузка через setChoices

Метод setChoices является основным инструментом для ручного наполнения списка после загрузки файла.

Сигнатура:

setChoices(choicesArray, valueKey, labelKey, replaceChoices)

Параметры

  • choicesArray — массив объектов
  • valueKey — ключ значения
  • labelKey — ключ отображаемого текста
  • replaceChoices — замена текущих данных

Поведение при replaceChoices = true

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


Загрузка CSV-файла и его преобразование

CSV требует дополнительного парсинга, так как не является структурированным объектом.

Пример CSV

1,Москва
2,Санкт-Петербург
3,Новосибирск

Реализация парсинга

function parseCSV(text) {
  return text
    .split('\n')
    .map(line => line.trim())
    .filter(line => line.length > 0)
    .map(line => {
      const [value, label] = line.split(',');

      return {
        value: value.trim(),
        label: label.trim(),
        selected: false,
        disabled: false
      };
    });
}

Загрузка файла

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  const reader = new FileReader();

  reader.onl oad = (e) => {
    const parsed = parseCSV(e.target.result);

    choicesInstance.clearChoices();
    choicesInstance.setChoices(parsed, 'value', 'label', true);
  };

  reader.readAsText(file);
});

Обновление данных без пересоздания инстанса

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

function updateChoices(data) {
  choicesInstance.removeActiveItems();
  choicesInstance.clearChoices();
  choicesInstance.setChoices(data, 'value', 'label', true);
}

Такой подход гарантирует:

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

Инкрементальная загрузка файлов

В некоторых сценариях требуется не замена, а добавление данных из файла.

function appendChoices(data) {
  choicesInstance.setChoices(data, 'value', 'label', false);
}

При replaceChoices = false новые элементы добавляются к существующим.

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


Чтение больших файлов и оптимизация

При загрузке больших JSON/CSV файлов возникает нагрузка на основной поток. Оптимизация включает:

1. Разбиение на чанки

function chunkArray(arr, size) {
  const result = [];

  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }

  return result;
}

2. Постепенная загрузка

async function loadInChunks(data) {
  const chunks = chunkArray(data, 200);

  for (const chunk of chunks) {
    choicesInstance.setChoices(chunk, 'value', 'label', false);

    await new Promise(resolve => setTimeout(resolve, 50));
  }
}

Такой подход снижает блокировку UI при больших объёмах данных.


Валидация данных перед загрузкой

Перед передачей данных в Choices.js необходимо обеспечить их корректность.

Проверка структуры

function validateItems(items) {
  return items.filter(item =>
    item &&
    typeof item.value !== 'undefined' &&
    typeof item.label === 'string' &&
    item.label.length > 0
  );
}

Использование

const safeData = validateItems(parsedData);

choicesInstance.clearChoices();
choicesInstance.setChoices(safeData, 'value', 'label', true);

Загрузка данных из нескольких файлов

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

function mergeFiles(files) {
  const readerPromises = Array.fr om(files).map(file => {
    return new Promise(resolve => {
      const reader = new FileReader();

      reader.onl oad = (e) => {
        const parsed = JSON.parse(e.target.result);
        resolve(parsed);
      };

      reader.readAsText(file);
    });
  });

  return Promise.all(readerPromises);
}

После объединения:

mergeFiles(fileInput.files).then(results => {
  const flat = results.flat();

  choicesInstance.clearChoices();
  choicesInstance.setChoices(flat, 'value', 'label', true);
});

Работа с кастомными свойствами при загрузке

Choices.js поддерживает customProperties, что позволяет сохранять дополнительные данные.

Пример расширенного JSON

[
  {
    "value": "1",
    "label": "Москва",
    "region": "Центральный",
    "population": 12000000
  }
]

Преобразование

const formatted = data.map(item => ({
  value: item.value,
  label: item.label,
  customProperties: {
    region: item.region,
    population: item.population
  }
}));

Очистка состояния перед новой загрузкой

При повторной загрузке файла важно полностью сбрасывать состояние:

function resetChoices() {
  choicesInstance.removeActiveItems();
  choicesInstance.clearChoices();
}

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


Обработка ошибок загрузки

При работе с файлами возможны ошибки чтения и парсинга.

function safeLoad(file) {
  const reader = new FileReader();

  reader.oner ror = () => {
    console.error('Ошибка чтения файла');
  };

  reader.onl oad = (e) => {
    try {
      const data = JSON.parse(e.target.result);
      const safe = validateItems(data);

      choicesInstance.setChoices(safe, 'value', 'label', true);
    } catch (err) {
      console.error('Ошибка обработки данных:', err);
    }
  };

  reader.readAsText(file);
}

Контроль состояния после загрузки

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

choicesInstance.setChoiceByValue('1');

или несколько значений:

choicesInstance.setChoiceByValue(['1', '2']);

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