Шаблон выбранного значения

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

Ключевая идея заключается в том, что выбранный элемент не обязан совпадать с текстом опции. Он может быть результатом вычисления, форматирования или даже сложной HTML-разметки.

В стандартном режиме отображение формируется из текстового содержимого <option>:

<select id="example">
  <option value="1">Москва</option>
  <option value="2">Санкт-Петербург</option>
  <option value="3">Казань</option>
</select>

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


Внутреннее представление выбранного элемента

При работе через JavaScript Slim Select преобразует исходные элементы в структуру объектов:

{
  value: "1",
  text: "Москва",
  selected: true
}

Именно объектная модель становится основой для шаблонизации. Отображение выбранного значения фактически зависит от того, как библиотека интерпретирует свойство text или результат пользовательской функции рендера.

Такой подход позволяет отделить данные от UI-слоя и управлять представлением без изменения DOM <select>.


Переопределение отображения через конфигурацию

Slim Select предоставляет механизм кастомизации через параметр конфигурации selected.

new SlimSelect({
  select: '#example',
  selected: (option) => {
    return option.text;
  }
});

Функция selected принимает объект выбранного элемента и возвращает строку или HTML, который будет отображён в поле выбора.

Это ключевой механизм формирования шаблона выбранного значения.


Формирование сложного шаблона

Функция рендера может использовать любые поля объекта, включая пользовательские атрибуты, добавленные в data-*.

<select id="users">
  <option value="1" data-role="admin" data-id="42">Иван Петров</option>
  <option value="2" data-role="editor" data-id="77">Мария Сидорова</option>
</select>
new SlimSelect({
  select: '#users',
  selected: (option) => {
    const role = option.element.dataset.role;
    return `${option.text} (${role})`;
  }
});

В этом случае шаблон выбранного значения становится зависимым не только от текста, но и от метаданных DOM-узла.


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

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

new SlimSelect({
  select: '#users',
  selected: (option) => {
    return `
      <div class="ss-selected-user">
        <span class="name">${option.text}</span>
        <span class="id">#${option.value}</span>
      </div>
    `;
  }
});

При таком подходе выбранное значение перестаёт быть простым текстом и становится мини-компонентом интерфейса.

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


Разделение отображения списка и выбранного значения

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

  • selected — отвечает за поле выбора
  • option — отвечает за элементы выпадающего списка
new SlimSelect({
  select: '#example',
  option: (option) => {
    return `<div>${option.text}</div>`;
  },
  selected: (option) => {
    return `<strong>${option.text}</strong>`;
  }
});

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


Работа с асинхронными данными и шаблоном

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

new SlimSelect({
  select: '#api-select',
  selected: (option) => {
    if (!option.data) return option.text;

    return `
      <span>${option.text}</span>
      <small>${option.data.category}</small>
    `;
  }
});

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


Обработка пустого состояния

Когда значение не выбрано, Slim Select отображает placeholder. Его можно рассматривать как отдельный шаблон состояния.

new SlimSelect({
  select: '#example',
  placeholder: 'Выберите значение',
  selected: (option) => {
    if (!option) return 'Пусто';
    return option.text;
  }
});

Фактически система работает с двумя состояниями:

  • выбранный элемент
  • отсутствие выбора

Каждое из них может иметь собственное отображение.


Условная стилизация выбранного значения

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

new SlimSelect({
  select: '#roles',
  selected: (option) => {
    const type = option.element.dataset.type;

    if (type === 'admin') {
      return `<span class="badge badge-red">${option.text}</span>`;
    }

    if (type === 'user') {
      return `<span class="badge badge-blue">${option.text}</span>`;
    }

    return option.text;
  }
});

Такой подход переносит часть логики отображения в слой шаблона, уменьшая необходимость внешнего CSS-управления состояниями.


Форматирование значений перед отображением

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

  • нормализацию регистра
  • добавление префиксов
  • объединение нескольких полей
new SlimSelect({
  select: '#products',
  selected: (option) => {
    const price = option.element.dataset.price;
    const currency = option.element.dataset.currency;

    return `${option.text} — ${price} ${currency}`;
  }
});

Шаблон выбранного значения становится слоем представления бизнес-данных.


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

В Slim Select возможно добавление иконографики через HTML-шаблон.

new SlimSelect({
  select: '#icons',
  selected: (option) => {
    const icon = option.element.dataset.icon;

    return `
      <span class="ss-item">
        <i class="${icon}"></i>
        ${option.text}
      </span>
    `;
  }
});

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


Интеграция с внешними состояниями приложения

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

let mode = 'compact';

new SlimSelect({
  select: '#example',
  selected: (option) => {
    if (mode === 'compact') {
      return option.text;
    }

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

Таким образом, отображение становится реактивным относительно состояния системы.


Ограничения шаблонизации выбранного значения

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

  • отсутствие автоматической экранизации HTML
  • необходимость самостоятельно обрабатывать null-значения
  • зависимость от структуры DOM <option>
  • потенциальные расхождения между списком и выбранным отображением

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


Композиция сложных шаблонов

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

new SlimSelect({
  select: '#complex',
  selected: (option) => {
    const meta = option.element.dataset;

    return `
      <div class="ss-complex">
        <div class="title">${option.text}</div>
        <div class="details">
          <span>${meta.city}</span>
          <span>${meta.status}</span>
        </div>
      </div>
    `;
  }
});

Подобная композиция превращает Slim Select в основу для построения мини-компонентов интерфейса без привлечения дополнительного UI-фреймворка.


Принципы устойчивого шаблона

При проектировании отображения выбранного значения ключевыми становятся следующие принципы:

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

Соблюдение этих принципов позволяет избежать рассинхронизации интерфейса и логики данных.