Работа с группами optgroup

Работа с группами опций в Slim Select основана на стандартной HTML-конструкции <optgroup>, которая позволяет логически объединять элементы выпадающего списка. Библиотека сохраняет нативную семантику группировки, расширяя её интерактивными возможностями: поиском внутри групп, кастомным рендерингом, управлением состоянием и программным контролем.

Базовая HTML-структура optgroup

Slim Select использует обычный <select> с вложенными группами:

<select id="example">
  <optgroup label="Фрукты">
    <option value="apple">Яблоко</option>
    <option value="banana">Банан</option>
  </optgroup>

  <optgroup label="Овощи">
    <option value="carrot">Морковь</option>
    <option value="potato">Картофель</option>
  </optgroup>
</select>

Каждый optgroup задаёт логическую категорию, а атрибут label используется как заголовок группы в интерфейсе Slim Select.

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

Инициализация Slim Select с группами

new SlimSelect({
  select: '#example'
});

При таком подключении библиотека:

  • считывает <optgroup> и <option>
  • формирует иерархическую структуру данных
  • отображает группы как отдельные секции списка
  • сохраняет связь между группой и элементами

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


Внутренняя модель данных групп

После парсинга HTML Slim Select преобразует структуру в объектный формат:

[
  {
    label: 'Фрукты',
    options: [
      { text: 'Яблоко', value: 'apple' },
      { text: 'Банан', value: 'banana' }
    ]
  },
  {
    label: 'Овощи',
    options: [
      { text: 'Морковь', value: 'carrot' },
      { text: 'Картофель', value: 'potato' }
    ]
  }
]

Каждая группа содержит:

  • label — название группы
  • options — массив элементов
  • внутренние метаданные состояния (активность, фильтрация, выбранные значения)

Такая структура используется при рендеринге и фильтрации.


Отображение групп в интерфейсе

Slim Select визуально разделяет группы:

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

HTML-структура внутри компонента выглядит логически так:

Фрукты
  Яблоко
  Банан

Овощи
  Морковь
  Картофель

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


Поиск внутри optgroup

Фильтрация работает не только по плоскому списку, но и внутри групп. При вводе текста Slim Select:

  • проверяет совпадения по option.text
  • скрывает элементы, не соответствующие запросу
  • скрывает группы, если в них нет совпадений

Пример поведения:

new SlimSelect({
  select: '#example',
  searchText: 'Поиск...'
});

Если пользователь вводит мор, результат будет:

Овощи
  Морковь

Группа «Фрукты» автоматически скрывается.


Управление состоянием групп через API

Slim Select не предоставляет прямого API для управления группой как сущностью, но позволяет управлять опциями внутри неё.

Выбор значений внутри групп

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

// установка значений
select.set(['apple', 'carrot']);

Группы при этом игнорируются как сущность — управление идёт через value.


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

select.getSelected();

Результат:

['apple', 'carrot']

Групповая структура в ответе не сохраняется, так как Slim Select возвращает плоский массив значений.


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

Группы можно добавлять программно через обновление <select> или через обновление данных (если используется data-режим).

Через DOM

const select = document.querySelector('#example');

const group = document.createElement('optgroup');
group.label = 'Напитки';

const option = document.createElement('option');
option.value = 'tea';
option.text = 'Чай';

group.appendChild(option);
select.appendChild(group);

// требуется пересоздание Slim Select
new SlimSelect({ select: '#example' });

Через data-инициализацию

new SlimSelect({
  select: '#example',
  data: [
    {
      label: 'Напитки',
      options: [
        { text: 'Чай', value: 'tea' },
        { text: 'Кофе', value: 'coffee' }
      ]
    }
  ]
});

В этом режиме структура optgroup полностью задаётся JavaScript-объектом.


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

Slim Select позволяет модифицировать рендеринг через addable, searchFilter, а также через переопределение шаблонов (в зависимости от конфигурации версии).

Основные сценарии кастомизации:

Изменение заголовков групп

Можно модифицировать label до передачи:

data: [
  {
    label: '? Товары',
    options: [...]
  }
]

Логическая сегментация

Группы часто используются для:

  • разделения типов данных
  • визуальной иерархии
  • ускорения навигации по списку

Фильтрация и скрытие пустых групп

При активной фильтрации Slim Select применяет правило:

  • если группа не содержит совпадающих элементов — она скрывается полностью
  • если хотя бы один элемент совпал — группа отображается

Это поведение не требует дополнительной настройки и встроено в алгоритм поиска.


Ограничения работы optgroup

Несмотря на поддержку групп, существуют ограничения:

  • выбор группы как целого невозможен без дополнительной логики
  • API работает только с value, а не с группами
  • порядок групп фиксируется структурой данных
  • вложенные группы (nested optgroup) не поддерживаются

Работа с disabled-группами

HTML поддерживает атрибут disabled у <optgroup>:

<optgroup label="Архив" disabled>
  <option value="old1">Старый элемент</option>
</optgroup>

Slim Select:

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

Поведение при множественном выборе

При включённом multiple: true:

  • опции из разных групп объединяются в общий список выбранных значений
  • порядок выбора не зависит от группировки
  • UI может отображать выбранные элементы без привязки к группе
new SlimSelect({
  select: '#example',
  settings: {
    multiple: true
  }
});

Программная фильтрация групп

При необходимости можно реализовать внешнюю фильтрацию:

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

function filterByGroup(groupName) {
  const options = document.querySelectorAll('#example optgroup');

  options.forEach(group => {
    group.style.display = group.label === groupName ? '' : 'none';
  });
}

После DOM-изменений требуется обновление или пересоздание компонента для синхронизации.


Использование optgroup в сложных интерфейсах

Группы особенно полезны при работе с:

  • каталогами товаров
  • списками регионов и городов
  • справочниками категорий
  • административными панелями

Типичный паттерн — комбинация серверной генерации групп и клиентской фильтрации через Slim Select.


Особенности рендеринга при больших данных

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

  • Slim Select оптимизирует отрисовку через виртуализацию (частично, в зависимости от версии)
  • скрытые элементы не участвуют в DOM-поиске
  • фильтрация выполняется по сокращённому набору данных

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