Отображение выбранных элементов

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

Внутри Slim Select выбранные значения хранятся как массив объектов состояния. Каждый объект содержит минимум:

  • text — отображаемый текст
  • value — значение option
  • selected — флаг состояния
  • дополнительные поля (disabled, placeholder, data-*)

При изменении выбора Slim Select пересобирает DOM-область выбранных элементов, синхронизируя её с состоянием.

Для одиночного выбора отображение строится вокруг одного элемента, который заменяет текст плейсхолдера. Для множественного выбора формируется набор “чипов” (tags-like элементов), каждый из которых является отдельной сущностью.

Отображение в режиме single select

В режиме одиночного выбора интерфейс содержит одну активную область отображения:

  • либо текст выбранного элемента
  • либо placeholder при отсутствии выбора

Структура DOM обычно включает контейнер отображения, в который подставляется текст выбранного значения.

Поведение:

  • при выборе option placeholder исчезает
  • текст заменяется на option.text
  • при очистке возвращается placeholder

Пример инициализации:

new SlimSelect({
  select: '#single'
})

В HTML:

<select id="single">
  <option value="">Select value</option>
  <option value="1">Alpha</option>
  <option value="2">Beta</option>
</select>

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

  1. пользователь выбирает Beta
  2. Slim Select обновляет state
  3. DOM заменяет текст placeholder на Beta
  4. внутренний input получает синхронизированное значение

Отображение в режиме multiple select

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

Типичная структура:

  • контейнер выбранных элементов
  • список “чипов”
  • поле ввода (если включён search)

Каждый чип содержит:

  • текст
  • кнопку удаления
  • идентификатор value

Пример:

new SlimSelect({
  select: '#multi',
  settings: {
    closeOnSelect: false
  }
})

HTML:

<select id="multi" multiple>
  <option value="1">Red</option>
  <option value="2">Green</option>
  <option value="3">Blue</option>
</select>

Поведение:

  1. выбор Red создаёт первый чип
  2. выбор Green добавляет второй
  3. каждый чип независимо рендерится и хранится в state
  4. удаление чипа обновляет state и DOM

Механизм рендеринга выбранных элементов

Slim Select не перерисовывает весь компонент при каждом изменении. Используется дифф-подход:

  • добавление → создаётся новый DOM-элемент
  • удаление → удаляется конкретный узел
  • изменение → обновляется текстовое содержимое

Это позволяет минимизировать перерасчёт layout.

Каждый выбранный элемент создаётся через внутренний шаблон:

  • контейнер ss-values
  • элемент ss-value
  • текст ss-value-text
  • кнопка удаления ss-value-delete

Управление отображением через данные option

Отображаемый текст всегда берётся из text, но может быть модифицирован через входные данные.

Пример кастомных данных:

new SlimSelect({
  select: '#multi',
  data: [
    { text: 'Item A', value: 'a' },
    { text: 'Item B', value: 'b', selected: true }
  ]
})

Здесь:

  • Item B будет отображён как выбранный
  • состояние selected: true инициализирует визуальные чипы

Плейсхолдер и его взаимодействие с выбранными элементами

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

Особенности:

  • в single select занимает основную область
  • в multiple select исчезает при первом выборе
  • не участвует в списке state после выбора

Если используется пустое значение:

<option data-placeholder="true">Choose item</option>

Slim Select интерпретирует его как визуальный placeholder, не как selectable option.

Перерисовка выбранных элементов при обновлении данных

При изменении данных через API:

let ss = new SlimSelect({ select: '#multi' })

ss.setData([
  { text: 'X', value: 'x' },
  { text: 'Y', value: 'y' }
])

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

  1. очищается контейнер выбранных элементов
  2. пересчитывается state
  3. заново создаются DOM-элементы чипов
  4. синхронизируется input value

При этом Slim Select старается сохранить совпадающие value, чтобы не сбрасывать выбор без необходимости.

Влияние disabled состояния на отображение выбранных элементов

Если option имеет disabled: true, но уже выбран:

  • элемент остаётся в отображении
  • но становится нефункциональным для удаления через стандартный UI (в зависимости от конфигурации)
  • состояние блокирует повторное взаимодействие
new SlimSelect({
  select: '#multi',
  data: [
    { text: 'Locked', value: '1', disabled: true, selected: true }
  ]
})

Управление отображением через методы API

Установка выбранных значений

ss.setSelected(['1', '2'])

Результат:

  • создаются два визуальных элемента
  • старые чипы удаляются
  • UI полностью синхронизируется

Получение отображаемого состояния

ss.getSelected()

Возвращает массив значений, соответствующих визуально отображённым элементам.

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

При большом количестве выбранных элементов:

  • контейнер расширяется по высоте
  • элементы переносятся на новую строку
  • возможна активация скролла (если задана фиксированная высота через CSS)

Slim Select не агрегирует значения в “+N items” по умолчанию, поэтому отображение остаётся детализированным.

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

Внутреннее обновление текста возможно при пересборке data:

ss.setData([
  { text: 'New Label', value: '1', selected: true }
])

При этом:

  • value остаётся тем же
  • отображение обновляется
  • DOM-узел пересоздаётся, а не редактируется inline

Особенности синхронизации с native select

Slim Select поддерживает двустороннюю синхронизацию:

  • изменение UI → обновление <select>
  • изменение <select> → обновление UI (при вызове refresh/инициализации)

Отображение выбранных элементов всегда базируется на актуальном состоянии DOM <select>, но не зависит от него напрямую в runtime, а через внутренний store.

Отображение при программной очистке

ss.setSelected([])

Результат:

  • удаляются все чипы
  • восстанавливается placeholder (если задан)
  • state очищается
  • input синхронизируется с пустым значением

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

Кастомизация структуры отображения

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

  • .ss-values
  • .ss-value
  • .ss-value-text
  • .ss-value-delete

Изменение отображения достигается исключительно стилями, без вмешательства в логику рендера, что сохраняет целостность состояния.

Состояние и реактивность отображения

Отображение выбранных элементов является реактивным слоем поверх состояния. Любое изменение state вызывает:

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

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