Сортировка товаров в каталоге Битрикса на Ajax

Инструкция
Как сделать сортировку товаров каталога по цене, названию и новинкам без перезагрузки страницы. Включаем AJAX_MODE в комплексном компоненте bitrix:catalog и добавляем безопасный переключатель.

7 мин 49 Обновлено 5 сентября Сложность: Средняя

TL;DR

  • Включаем AJAX_MODE = Y в комплексном компоненте bitrix:catalog – свой JS не нужен.
  • Перед вызовом catalog.section передаём ELEMENT_SORT_FIELD и ELEMENT_SORT_ORDER из GET.
  • Принимаем только разрешённые поля сортировки – защита от подмены поля.
  • Поле цены – catalog_PRICE_N, где N – ID типа цены BASE.
  • Активную ссылку помечаем классом и aria-current для доступности.

Сортировка каталога по цене, названию или новинкам без перезагрузки страницы делает выбор товара удобнее и не сбрасывает позицию прокрутки. В 1С-Битрикс это решается штатным AJAX-режимом комплексного компонента bitrix:catalog – без единой строки собственного JavaScript. Ниже – рабочий приём и разбор, почему он работает.

Шаг 1. Включаем AJAX в компоненте каталога

В настройках комплексного компонента bitrix:catalog включаем AJAX-режим – параметр "AJAX_MODE" => "Y". Тогда при переходе по ссылкам сортировки компонент подгрузит только свою область, а не всю страницу.

Шаг 2. Расширяем список полей сортировки

В шаблоне комплексного компонента (например, section_horizontal.php) перед вызовом вложенного bitrix:catalog.section добавляем код, который читает параметр сортировки из адреса и передаёт его во вложенный компонент. Обратите внимание: мы принимаем не любое значение из $_GET, а только заранее разрешённые – это защищает от подстановки произвольных полей сортировки (SQL-инъекций через имя поля).

if ($_GET["sort"] == "name" ||
    $_GET["sort"] == "catalog_PRICE_1" || // после catalog_PRICE_ указывается ID вашей базовой цены
    $_GET["sort"] == "timestamp_x") {

    $arParams["ELEMENT_SORT_FIELD"] = $_GET["sort"];
    $arParams["ELEMENT_SORT_ORDER"] = ($_GET["method"] == "asc" ? "asc" : "desc");
}

Здесь важны два момента: ELEMENT_SORT_FIELD – по какому полю сортируем, ELEMENT_SORT_ORDER – направление. Значение method тоже стоит приводить к одному из двух допустимых значений (asc/desc), а не подставлять из $_GET напрямую.

Значения полей сортировки

  • name – по названию товара;
  • catalog_PRICE_1 – по цене, где 1 – это ID вашего типа цены (Магазин → Настройки → Типы цен, базовая цена имеет код BASE);
  • timestamp_x – по дате изменения, удобно для блока «Новые поступления»;
  • sort – по полю «Сортировка» элемента инфоблока.

Шаг 3. Ссылки-переключатели в шаблоне

В шаблоне вложенного компонента bitrix:catalog.section (файл template.php) выводим ссылки сортировки. Активную ссылку помечаем классом и атрибутом aria-current="true" для доступности:

<p>Сортировать по:
    <a <?if ($_GET["sort"] == "name"):?> class="actived" aria-current="true" <?endif;?>
       href="<?=$arResult["SECTION_PAGE_URL"]?>?sort=name&method=asc">Названию</a> |

    <a <?if ($_GET["sort"] == "catalog_PRICE_1" && $_GET["method"] == "desc"):?> class="actived" aria-current="true" <?endif;?>
       href="<?=$arResult["SECTION_PAGE_URL"]?>?sort=catalog_PRICE_1&method=desc">Убыванию цены</a> –
    <a <?if ($_GET["sort"] == "catalog_PRICE_1" && $_GET["method"] == "asc"):?> class="actived" aria-current="true" <?endif;?>
       href="<?=$arResult["SECTION_PAGE_URL"]?>?sort=catalog_PRICE_1&method=asc">Возрастанию цены</a> |

    <a <?if ($_GET["sort"] == "timestamp_x"):?> class="actived" aria-current="true" <?endif;?>
       href="<?=$arResult["SECTION_PAGE_URL"]?>?sort=timestamp_x&method=desc">Новые поступления</a>
</p>

Обратите внимание: для цены удобно различать в подсветке направление сортировки (по возрастанию и по убыванию – это одно поле, но разный method), поэтому в условии проверяется и sort, и method.

Почему это работает и подводные камни

  • AJAX без своего JS. При AJAX_MODE = Y Битрикс сам перехватывает переходы по ссылкам внутри области компонента и подменяет её содержимое, сохраняя адрес в истории браузера.
  • Кеш компонента. Параметры сортировки должны попадать в ключ кеша, иначе разные варианты сортировки будут отдавать одинаковый закешированный результат. Комплексный компонент учитывает $_GET в дополнительном кеше, но при своих доработках это стоит проверять.
  • ЧПУ (SEF). При включённом SEF-режиме следите, чтобы GET-параметры сортировки корректно добавлялись к «красивым» адресам разделов.
  • Тип цены. Если сортировка по цене не срабатывает – проверьте, верно ли указан ID базовой цены в catalog_PRICE_N и выбран ли нужный тип цены в настройках компонента (блок «Цены» → «Тип цены»).

Похожие приёмы работы с параметрами и выборкой из инфоблоков – в гайдах «Фильтрация элементов по полю Привязка к элементам» и «Получить ID из GET и вывести элементы инфоблока». А чтобы выводить блоки сортировки только на нужных страницах – см. «Вывод блоков только на определённых страницах».

Частые вопросы

Нужен ли собственный JavaScript для Ajax-сортировки в Битриксе?

Нет. Достаточно включить AJAX_MODE = Y в комплексном компоненте bitrix:catalog – Битрикс сам перехватит переходы по ссылкам сортировки и обновит только область каталога.

Что означает значение catalog_PRICE_1 в сортировке?

Это сортировка по цене, где число после catalog_PRICE_ – ID вашего типа цены. Базовая цена имеет код BASE, её ID смотрят в Магазин → Настройки → Типы цен.

Почему нельзя брать поле сортировки прямо из $_GET?

Имя поля попадает в SQL-запрос выборки, поэтому произвольное значение из адреса – риск инъекции. Принимайте только заранее разрешённый список полей (name, catalog_PRICE_N, timestamp_x).

Сортировка по цене не работает – что проверить?

Проверьте, верно ли указан ID базовой цены в catalog_PRICE_N, и выбран ли нужный тип цены в настройках компонента в блоке «Цены» → «Тип цены».

Материалы по теме

Что почитать дальше по этой теме

Инструкция Фильтрация элементов по полю «Привязка к элементам» в Битрикс Как отфильтровать элементы инфоблока по множественному свойству типа «Привязка к элементам» (E). Разбираем прямой фильтр PROPERTY_CODE, связку через второй инфоблок в два шага и подзапрос CIBlockElement::SubQuery, который убирает лишний цикл на PHP. 7 мин 64 17 августа 2017 Инструкция Получить ID из GET и вывести элементы и свойства инфоблока Как в 1С-Битрикс взять ID элемента из GET-параметра, безопасно его отфильтровать и выбрать поля и свойства элемента инфоблока. Разбираем GetNextElement, защиту от дублей при множественных свойствах и D7-альтернативу. 8 мин 55 19 июля 2019 Инструкция Вывод блоков только на определённых страницах сайта Как в 1С-Битрикс показать баннер, форму или блок только на нужных страницах. Разбираем API $APPLICATION->GetCurPage и GetCurDir, разницу между физическим и SEF-адресом, проверку по разделу и типичные ошибки с ЧПУ. 7 мин 58 24 октября 2018 Инструкция Создать вкладки (tabs) из свойств элемента инфоблока Как сделать вкладки на странице элемента инфоблока Битрикса из его свойств. Собираем контент из DISPLAY_PROPERTIES в шаблоне компонента и добавляем доступный (a11y) переключатель на чистом JS – с role=tab/tabpanel, aria-selected и навигацией с клавиатуры, без jQuery. 8 мин 39 18 мая 2017