Шаблон option

Базовая модель данных option

Внутри Slim Select каждый пункт списка строится на основе стандартного HTML <option> или объекта данных, если используется программная инициализация. Независимо от источника, библиотека приводит данные к единой структуре, где ключевыми полями выступают:

  • text — отображаемый текст
  • value — значение элемента
  • disabled — состояние недоступности
  • selected — начальное выделение
  • innerHTML — расширенное HTML-содержимое (если разрешено)

HTML-основа:

<select id="mySelect">
  <option value="1">Первый элемент</option>
  <option value="2" disabled>Второй элемент</option>
  <option value="3">Третий элемент</option>
</select>

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


Преобразование option в объект

При программной инициализации структура может задаваться напрямую:

new SlimSelect({
  select: '#mySelect',
  data: [
    { text: 'Первый элемент', value: '1' },
    { text: 'Второй элемент', value: '2', disabled: true },
    { text: 'Третий элемент', value: '3' }
  ]
});

Каждый объект в массиве data становится шаблоном option. Это ключевой слой, на котором строится кастомизация отображения.


Механизм шаблонизации option

В Slim Select шаблон option отвечает за то, как элемент списка визуально представлен в dropdown. Основной механизм заключается в функции рендеринга, которая получает данные option и возвращает HTML-строку.

Типовая форма:

new SlimSelect({
  select: '#mySelect',
  render: {
    option: (data, option) => {
      return `<div class="custom-option">${data.text}</div>`;
    }
  }
});

Параметры функции рендера

  • data — нормализованный объект option
  • option — исходный DOM-элемент (если select основан на HTML)

Использование DOM-элемента позволяет извлекать кастомные атрибуты:

<option value="1" data-icon="star">Первый</option>
render: {
  option: (data, option) => {
    const icon = option.getAttribute('data-icon');
    return `
      <div class="option-item">
        <span class="icon">${icon}</span>
        <span class="label">${data.text}</span>
      </div>
    `;
  }
}

HTML внутри option и innerHTML

Одним из расширений шаблона option является поддержка HTML-содержимого. Если innerHTML передаётся явно, Slim Select может использовать его вместо text.

data: [
  {
    value: '1',
    text: 'Ignored text',
    innerHTML: '<strong>Жирный текст</strong>'
  }
]

В рендере:

render: {
  option: (data) => {
    return `<div class="option-html">${data.innerHTML ?? data.text}</div>`;
  }
}

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


Кастомные атрибуты option

Шаблон option часто расширяется через data-* атрибуты:

<option value="1" data-price="1200" data-status="available">
  Товар 1
</option>

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

render: {
  option: (data, option) => {
    const price = option.getAttribute('data-price');
    const status = option.getAttribute('data-status');

    return `
      <div class="product-option">
        <div class="title">${data.text}</div>
        <div class="meta">
          <span class="price">${price}</span>
          <span class="status">${status}</span>
        </div>
      </div>
    `;
  }
}

Такой подход переводит option из простого текста в полноценный UI-компонент.


Разделение отображения: option и selected

Внутренний шаблон option часто отличается от отображения выбранного значения. В Slim Select это разделение логически важно: dropdown и поле выбора могут иметь разные представления одного и того же объекта.

new SlimSelect({
  select: '#mySelect',
  render: {
    option: (data) => {
      return `<div class="dropdown-item">${data.text}</div>`;
    },
    selected: (data) => {
      return `<div class="selected-item">${data.text}</div>`;
    }
  }
});

Разделение позволяет:

  • упрощать dropdown (подробный UI)
  • упрощать selected (компактный UI)
  • снижать визуальную нагрузку

Условная отрисовка option

Шаблон option часто зависит от состояния данных:

render: {
  option: (data, option) => {
    if (data.disabled) {
      return `<div class="option disabled">${data.text}</div>`;
    }

    if (option?.dataset?.premium === "true") {
      return `<div class="option premium">${data.text} ⭐</div>`;
    }

    return `<div class="option">${data.text}</div>`;
  }
}

Таким образом шаблон становится реактивным к данным, а не статическим.


Группировка option и шаблон внутри группы

Когда используются группы (optgroup), шаблон option дополняется структурой группы:

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

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

render: {
  option: (data, option) => {
    const group = option.closest('optgroup')?.label;

    return `
      <div class="option">
        <div class="text">${data.text}</div>
        ${group ? `<div class="group">${group}</div>` : ''}
      </div>
    `;
  }
}

Производительность шаблонов option

При работе с большими списками шаблон option становится критическим элементом производительности. В Slim Select важно учитывать:

  • минимизацию DOM-строк
  • отсутствие тяжёлых вычислений внутри render-функции
  • кэширование вычисляемых значений

Пример оптимизации:

const cache = new Map();

function renderOption(data) {
  if (cache.has(data.value)) {
    return cache.get(data.value);
  }

  const html = `<div class="option">${data.text}</div>`;
  cache.set(data.value, html);
  return html;
}

Интеграция шаблона option с внешними данными

Часто option строится из API-ответов:

fetch('/api/items')
  .then(res => res.json())
  .then(items => {
    new SlimSelect({
      select: '#mySelect',
      data: items.map(item => ({
        text: item.name,
        value: item.id,
        innerHTML: `<strong>${item.name}</strong>`
      }))
    });
  });

Шаблон option в этом случае становится слоем визуализации над серверной моделью данных.


Динамическое обновление option-шаблона

В Slim Select возможно изменение данных и перерисовка списка без пересоздания экземпляра:

const slim = new SlimSelect({
  select: '#mySelect',
  data: []
});

slim.setData([
  { text: 'Новый элемент 1', value: '1' },
  { text: 'Новый элемент 2', value: '2' }
]);

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


Итоговая роль шаблона option

Шаблон option в Slim Select выступает слоем между данными и интерфейсом. Он определяет:

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

Фактически именно шаблон option превращает стандартный <select> в гибкий компонент интерфейса с управляемой визуализацией и логикой представления данных.