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

В основе Slim Select лежит модель, при которой DOM-элемент <select> выступает источником состояния, а библиотека синхронизирует визуальный слой с внутренним представлением данных. Любое динамическое изменение опций требует обновления двух уровней: структуры данных и отрисованного интерфейса.

Ключевой принцип заключается в том, что Slim Select не просто «рисует» список, а поддерживает внутренний массив элементов, который используется для фильтрации, выбора и отображения состояния. Поэтому прямые манипуляции с DOM без уведомления экземпляра приводят к рассинхронизации.


Полная замена набора опций (setData)

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

Метод setData полностью заменяет текущие опции:

const select = new SlimSelect({
  select: '#cities'
});

select.setData([
  { text: 'Алматы', value: 'almaty' },
  { text: 'Астана', value: 'astana' },
  { text: 'Шымкент', value: 'shymkent' }
]);

После вызова происходит:

  • очистка текущих опций;
  • перерисовка списка;
  • сброс невалидных выбранных значений;
  • обновление поискового индекса.

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


Добавление новых элементов (addOption)

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

Типовой сценарий — динамическое добавление нового значения после пользовательского ввода:

select.addOption({ text: 'Караганда', value: 'karaganda' });

При добавлении выполняется:

  • вставка элемента в внутренний массив;
  • обновление DOM-списка;
  • пересчёт индексов поиска;
  • сохранение текущего выбора.

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


Удаление и очистка данных

Удаление элементов требует аккуратного обращения с состоянием выбранных значений. Slim Select синхронизирует выбранные элементы с доступными опциями, поэтому удаление выбранного значения автоматически влияет на модель.

Удаление одного элемента:

select.removeOption('astana');

Очистка всего набора данных:

select.setData([]);

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

select.set([]);

При удалении важно учитывать:

  • активные выбранные значения могут быть сброшены;
  • фильтр поиска обновляется автоматически;
  • UI переходит в состояние «пустого списка», если опций нет.

Обновление выбранных значений

Манипуляции с выбором напрямую связаны с синхронизацией состояния. Slim Select предоставляет метод установки значений программно.

select.set(['almaty', 'shymkent']);

Для одиночного выбора:

select.set('almaty');

Механика работы:

  • проверка валидности значений относительно текущих опций;
  • обновление внутреннего состояния;
  • синхронизация DOM <select>;
  • триггер событий изменения.

Если значение отсутствует в списке, оно игнорируется без ошибки, что позволяет безопасно применять серверные данные.


Асинхронная подгрузка данных

Частый сценарий динамического обновления связан с загрузкой данных через API. Slim Select не навязывает встроенный AJAX-слой, но легко интегрируется с fetch-запросами.

fetch('/api/cities')
  .then(res => res.json())
  .then(data => {
    select.setData(
      data.map(item => ({
        text: item.name,
        value: item.id
      }))
    );
  });

При асинхронной загрузке важно учитывать временные состояния:

  • пустой список до завершения запроса;
  • предотвращение повторных вызовов;
  • сохранение выбранных значений при обновлении (если требуется логика merge).

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

const current = select.selected();

fetch('/api/cities')
  .then(res => res.json())
  .then(data => {
    select.setData(data);

    const valid = current.filter(v =>
      data.some(item => item.value === v)
    );

    select.set(valid);
  });

Инкрементальные обновления и синхронизация состояния

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

Сценарий синхронизации с сервером:

function syncOptions(serverData) {
  const existing = select.data();

  const toAdd = serverData.filter(
    s => !existing.some(e => e.value === s.id)
  );

  const toRemove = existing.filter(
    e => !serverData.some(s => s.id === e.value)
  );

  toRemove.forEach(item => {
    select.removeOption(item.value);
  });

  toAdd.forEach(item => {
    select.addOption({
      text: item.name,
      value: item.id
    });
  });
}

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


Обработка состояний загрузки и пустых данных

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

Пустое состояние:

select.setData([]);

Имитация загрузки:

select.disable();

После загрузки:

select.enable();

Типовая модель поведения:

  • disable во время запроса;
  • очистка или временное отображение плейсхолдера;
  • setData после получения данных;
  • enable после завершения синхронизации.

Синхронизация с пользовательским вводом и поиском

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

Пример фильтрации:

select.setData(
  allItems.filter(item =>
    item.name.toLowerCase().includes(query.toLowerCase())
  )
);

При частых обновлениях (например, live search) применяется debounce, чтобы избежать перегрузки:

let timeout;

input.addEventListener('input', (e) => {
  clearTimeout(timeout);

  timeout = setTimeout(() => {
    upd ateData(e.target.value);
  }, 300);
});

Частые ошибки при динамическом обновлении

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

Прямое изменение DOM без API Slim Select

document.querySelector('#select').innerHTML += '<option>...</option>';

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


Несоответствие выбранных значений новым данным

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


Частые повторные setData при загрузке

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


Игнорирование асинхронного состояния

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


Обновление данных в реактивных интерфейсах

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

Типовой паттерн:

  • состояние хранится в store;
  • изменения данных триггерят setData;
  • выбор синхронизируется через se t;
  • DOM не модифицируется напрямую.

Пример интеграции:

store.subscribe(state => {
  select.setData(state.options);
  select.set(state.selected);
});

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