
Фильтр выпадающим списком
Выпадающий список <select> — дальше селект — вместо флажков собирается из двух своих чанков. Готового в поставке нет, но JS обрабатывает селект сам.
Задача
Вывести значения одного фильтра селектом, а остальные оставить флажками. Обычно это нужно, когда значений много — например, несколько десятков производителей — и выбирают одно.
С селектом JS уже умеет:
- отправлять форму при выборе значения;
- сбрасывать селект кнопкой сброса формы и крестиком в блоке «Выбрано»;
- после фильтрации блокировать значения, по которым не осталось товаров;
- по кнопке «Назад» переключать селект на значение, выбранное раньше;
- учитывать выбор в счётчике у заголовка фильтра, если в чанке обёртки есть элемент
data-filter-badge, как в стандартномmfilter.filter.

На снимке список раскрыт атрибутом size, чтобы были видны заблокированные значения.
Решение
Чанк значения
Создайте чанк, например catalog.filter.item:
{* Ключи фильтров, которые выводятся селектом. Тот же набор — в чанке обёртки *}
{set $selectKeys = ['vendor']}
{if $key in $selectKeys}
<option value="{$value | esc}"{if $active} selected{/if}{if $disabled} disabled{/if}>{$label | esc}</option>
{else}
<label class="mfilter-item">
<input type="{if $multiple}checkbox{else}radio{/if}" name="{$key}{if $multiple}[]{/if}" value="{$value | esc}"{if $active} checked{/if}{if $disabled} disabled{/if}>
{$label | esc} <span class="mfilter-count">{$count}</span>
</label>
{/if}Чанк обёртки
Создайте чанк, например catalog.filter:
{set $selectKeys = ['vendor']}
<div data-filter-key="{$key}">
<div data-filter-label="{$label | esc}">{$label | esc}</div>
{if $key in $selectKeys}
<select name="{$key}">
{* Первая опция селекта — «ничего не выбрано» *}
<option value="">Все варианты</option>
{* Остальные опции селекта выводит чанк значения *}
{$items}
</select>
{else}
{$items}
{/if}
</div>Вызов
{'!mFilterForm' | snippet : [
'tpl' => 'catalog.filter',
'tplItem' => 'catalog.filter.item',
]}В примерах только то, без чего селект не заработает. Если у вас уже есть оформленный чанк обёртки, например копия стандартного mfilter.filter, добавьте в него ту же ветку {if $key in $selectKeys} вокруг {$items}. Атрибуты data-filter-key и data-filter-label у блока фильтра оставьте: по ним блок «Выбрано» находит название фильтра.
Все переменные обоих чанков — в разделе Чанки mFilterForm.
Почему два чанка
mFilterForm отрисовывает фильтр в два слоя: сначала каждое значение чанком значения, затем обёртку, куда значения попадают готовым HTML в $items. Поэтому опции селекта выводит чанк значения, а сам <select> — обёртка.
Чанк значения выбирается по типу фильтра, а не по ключу. Настройки «показывать селектом» в наборе фильтров нет:
| Тип фильтра | Чанк значения |
|---|---|
number | &tplSlider |
colors | &tplColor |
boolean | &tplBoolean |
| остальные | &tplItem |
Поэтому в $selectKeys можно добавлять только фильтры, значения которых идут через &tplItem.
Список ключей повторяется в обоих чанках: чанк значения отрисовывается раньше обёртки, и общих переменных у них нет.
Правила разметки
Без любого из этих правил селект отрисуется, но будет работать неправильно — и без ошибок в консоли.
name без [], если значение одно
{* Так *}
<select name="{$key}">
{* Не так *}
<select name="{$key}[]">Блокировка пустых значений и счётчик у заголовка ищут селект строго по select[name="vendor"]. С vendor[] пустые значения перестанут блокироваться, а счётчик — считать выбор. Сразу после загрузки страницы разницы не видно: при загрузке пустые значения блокирует сервер, а скрипт — только после фильтрации.
Первая опция селекта — «Все варианты»
<select name="{$key}">
<option value="">Все варианты</option>
{$items}
</select>Без этой опции выбор в самом селекте не отменить — только кнопкой сброса формы или крестиком в блоке «Выбрано». Пустое значение снимает фильтр, и JS опцию никогда не блокирует. Стоит она в чанке обёртки перед {$items}: чанк значения выводит только значения фильтра.
Несколько значений — multiple вместе с []
{* Так *}
<select name="{$key}[]" multiple>
{$items}
</select>
{* Не так *}
<select name="{$key}" multiple>Селект с multiple и [] отправляет все выбранные значения, снимает их по одному крестиком в блоке «Выбрано» и возвращает по «Назад». Опция «Все варианты» ему не нужна: чтобы снять выбор, достаточно снять выделение со всех опций.
Без [] в имени «Назад» вернёт в селект только первое из выбранных значений, а следующее изменение формы молча снимет остальные.
Но и с [] у селекта с multiple есть ограничения:
- пустые значения не блокируются;
- счётчик у заголовка выбор не считает;
- кнопка сброса формы сейчас оставляет выделенным первое значение, и следующее изменение формы его применит.
Если это мешает, выводите фильтр флажками: уберите его ключ из $selectKeys в обоих чанках.
Число товаров в опции селекта
Проще всего число в опции не выводить — как в чанке значения выше. После фильтрации JS обновляет число у флажков, а у опций селекта только блокирует пустые. Число в тексте опции устареет после первого же выбора в соседнем фильтре.
Если число нужно, сохраните название в data-label:
<option value="{$value | esc}" data-label="{$label | esc}"{if $active} selected{/if}{if $disabled} disabled{/if}>{$label | esc} ({$count})</option>И обновляйте текст после каждой фильтрации — скрипт в любом месте страницы:
document.addEventListener('mfilter:success', (e) => {
const suggestions = e.detail.response.suggestions || {};
document.querySelectorAll('select option[data-label]').forEach((option) => {
const filter = suggestions[option.parentElement.name];
if (!filter) return;
const item = (filter.values || []).find((v) => String(v.value) === option.value);
option.textContent = `${option.dataset.label} (${item ? item.count : 0})`;
});
});Если не работает
| Симптом | Причина |
|---|---|
Внутри блока флажков появились отдельные <option> | Ключ есть в $selectKeys чанка значения, но нет в обёртке |
| Селект пустой, а значения выведены флажками рядом | Ключ есть в обёртке, но нет в чанке значения |
| Селект обернул цветные образцы или переключатель | В $selectKeys попал фильтр типа colors или boolean |
| Пустые значения не блокируются после фильтрации | name с []. У селекта с multiple это ограничение JS — см. «Несколько значений» |
| Счётчик у заголовка фильтра не считает выбор в селекте | То же: name с [] |
После «Назад» в селекте с multiple выбрано одно значение из нескольких | multiple без [] в имени |
После сброса формы в селекте с multiple выделено первое значение | Ограничение JS — см. «Несколько значений» |
| Выбор не отменить в самом селекте | В чанке обёртки нет опции «Все варианты» |
| Число товаров в опции селекта не меняется после фильтрации | Число выведено в текст без скрипта обновления — см. «Число товаров в опции селекта» |
