Чтобы написать кастомную сортировку (по аналогии можно реализовать фильтрацию элементов), потребуется код и логика, которые описаны на этой странице. Можно доработать, но для описания общей концепции приведенного кода будет вполне достаточно.
Подключение компонента bitrix:catalog.section
Компонент и логика, связанная с ним, будет выглядеть следующим образом:
<!--Обратить внимание на следующие моменты:
1. id="catalog_section" - обязательно нужен, чтобы сюда загрузить итоговые значения сортировки
2. Настройка стандартной сортировки через компонент при такой реализации сломается. Так как мы в поля "ELEMENT_SORT_FIELD" и "ELEMENT_SORT_ORDER" передаем вместо $arParams свои кастомные значения
-->
<?
global $APPLICATION;
$curPage = $APPLICATION->GetCurPage();
$request = Bitrix\Main\Application::getInstance()->getContext()->getRequest();
$request->getPostList();
?>
<div class="category__inner" id="catalog_section">
<?php
if (!empty($_SESSION['SORT'][$curPage])) { //если в сессии для есть хоть какие-то сохраненные значения для сортировки для текущей страницы, мы присваиваем их нашим переменным, которые передаем в компонент
$sortField = $_SESSION['SORT'][$curPage]['field'];
$sortOrder = $_SESSION['SORT'][$curPage]['order'];
}
if($request["SORT"] == "Y") //если есть свежие значения сортировки, переданные в реквесте, мы перезапишем текущие значения сортировки в сессии и включим буферизацию вывода битрикса
{
list($sortField, $sortOrder) = explode( '_', $request['DATA_SORT_VALUES']);
$_SESSION['SORT'][$curPage] = [
'field' => $sortField,
'order' => $sortOrder
];
$APPLICATION->RestartBuffer();
}
?>
<?php $intSectionID = $APPLICATION->IncludeComponent(
"bitrix:catalog.section",
"catalog",
array(
"IBLOCK_TYPE" => $arParams["IBLOCK_TYPE"],
"IBLOCK_ID" => $arParams["IBLOCK_ID"],
"ELEMENT_SORT_FIELD" => $sortField,
"ELEMENT_SORT_ORDER" => $sortOrder,
//остальные параметры компонента
),
$component
); ?>
<? if($request["SORT"] == "Y") //это нужно, чтобы область буфера грузилась ДО этого момента а ниже не грузилась
{
die();
} ?>
</div>При таком подходе соблюдается логика:
- Так как буферизуем только область вывода компонента, то код, который находится выше или ниже компонента, отработает (например хедер, футер и прочие элементы будут загружены).
- Благодаря тому, что мы буферизуем определенную область, только код, находящийся внутри этой области попадет в буфер, а значит, в вывод на экран (код будет возвращен пользователю).
- Так как отработала вся страница, но в вывод попала только часть, ограниченная областью буферизации, ajax в responce вернет только код, который содержится внутри буферизуемой области.
- Так как при передаче данных через ajax, в запросе мы передаем нужные post — данные для сортировки, компонент эти данные обработает и отсортирует элементы так, как нам нужно. Соответственно, в буферизуемую область попадет уже отсортированный как нам нужно контент.
- Последнее действие после того, как ajax получил в ответе отсортированные элементы — загрузить их в обозначенную область (в нашем случае это div с id=catalog_section )
Написание логики по нажатию кнопки сортировки bitrix:catalog.section (на js)
Общий принцип следующий:
- Получаем нужные данные — кнопки для сортировки
- Отправляем ajax запрос на текущую страницу с нужными данными
- Ответ, который придет, вставляем с нужный div — Обертку над компонентом
document.addEventListener("DOMContentLoaded", function() {
applyFilter(); // Инициируем функцию после загрузки страницы
});
function applyFilter() {
const buttons = document.querySelectorAll('span[data-sort]');
buttons.forEach(button => {
button.addEventListener('click', () => {
const dataSortValue = button.getAttribute('data-sort');
let formData = new FormData();
formData.append('DATA_SORT_VALUES', dataSortValues);
formData.append('SORT', 'Y');
fetch(window.location.href, {
method: 'POST',
body: formData,
})
.then(response => response.text())
.then(response => {
let catalogSectionBlock = document.getElementById('catalog_section');
catalogSectionBlock.innerHTML = response;
applyFilter(); // Вызываем функцию заново после получения ответа и загрузки нового содержимого
}).catch(error => console.error(error));
});
});
}Подключение обертки для самой сортировки и логика вывода выбранной сортировки
Чтобы после перезагрузки страницы выбранное значение сортировки было отображено в блоке сортировки (часть этой логики в верстке сортировки):
<?php
/**
* @var string $curPage
* @var array $arResult
*/
$sortInstalled = '';
//Чтобы выбранное значение сортировки выводилось после перезагрузки страницы на текущей странице
if (!empty($_SESSION['SORT'][$curPage])) {
$sortField = $_SESSION['SORT'][$curPage]['field'];
$sortOrder = $_SESSION['SORT'][$curPage]['order'];
$sortInstalled = $sortField.'_'.$sortOrder;
}
//Определяем возможные значения сортировки
$sortValues = [
'name_asc' => 'По имени (возрастание)',
'name_desc' => 'По имени (убывание)',
'date_asc' => 'По дате (возрастание)',
'date_desc' => 'По дате (убывание)',
];
?>«Представление» блока сортировки и часть логики по выводу актуального значения сортировки:
<?php
use Bitrix\Main\Localization\Loc;
/**
* @var array $sortValues
* @var array $arResult
* @var string $sortInstalled
*/
include 'sort_logic.php'
?>
<!-- Внешний вид блока с сортировкой элементов. Здесь обратить внимание на следующие моменты:
1. атрибут "data-sort", в который нужно передать значения сортировки. В значениях должен быть параметр, по которому проводится сортировка и вариант сортировки ("по возрастанию" или "по убыванию")
Остальное думаю будет понятно по контексту
-->
<div class="category-sort">
<button type="button" class="category-sort__btn" data-btn>
<svg astro-icon="sort">
<use xlink:href="#astroicon:sort"></use>
</svg><?= ($sortInstalled)?$sortValues[$sortInstalled]:Loc::getMessage('ARRANGE') ?></button>
<div class="category-sort__container">
<?php foreach ($sortValues as $k =>$val):?>
<label class="category-sort-item">
<input type="radio" <?php if($sortInstalled && $sortInstalled == $k):?>checked<?php endif; ?> name="sort">
<span class="category-sort-item__inner" data-sort="<?=$k;?>">
<?=$val;?>
</span>
</label>
<?php endforeach; ?>
</div>
</div>
Об авторе
Сергей Житников - Веб-разработчик
Занимаюсь веб-разработкой более 5 лет. Специализируюсь на создании адаптивных сайтов и веб-приложений на HTML5, CSS3 и JavaScript. Работаю с популярными CMS и фреймворками, а также уделяю большое внимание оптимизации производительности и чистоте кода.
Есть проект или идея? Буду рад помочь!
Связаться со мной