Вводные
Работаем с комплексным компонентом каталога. Товары лежат в корне, поэтому работаем в sections.php
Сортировать будем по цене (возрастание, убывание), по свойству "Новинка" и свойству "Набор".
Можно добавить любые другие свойства. По умолчанию будет применяться сортировка по свойству "Новинка".
Запоминаем выбор пользователя на 16 часов, записывая сортировку в cookie.
Обновляем товары без перезагрузки страницы.
sections.php
/**
* Типы Цен и Сортировка
*/
$sortPrice = $arParams['ELEMENT_SORT_FIELD2'];
// Проверяем приоритеты:
// 1. AJAX запрос, 2. GET параметр, 3. Cookie, 4. По умолчанию.
$currentSort = 'property_NOVINKA'; // Значение по умолчанию.
// Проверяем AJAX запрос.
if ($_REQUEST['sort_ajax'] === 'Y' && $_REQUEST['sort']) {
$currentSort = $_REQUEST['sort'];
}
// Проверяем GET параметр
else if ($_REQUEST['sort']) {
$currentSort = $_REQUEST['sort'];
}
// Проверяем cookie (действительна 16 часов)
else if ($_COOKIE['catalog_sort_order']) {
$currentSort = $_COOKIE['catalog_sort_order'];
}
// Применяем сортировку
switch ($currentSort) {
case 'price_asc':
$arParams['ELEMENT_SORT_FIELD'] = $sortPrice;
$arParams['ELEMENT_SORT_ORDER'] = 'asc';
$arParams['ELEMENT_SORT_FIELD2'] = 'ID';
$arParams['ELEMENT_SORT_ORDER2'] = 'asc';
break;
case 'price_desc':
$arParams['ELEMENT_SORT_FIELD'] = $sortPrice;
$arParams['ELEMENT_SORT_ORDER'] = 'desc';
$arParams['ELEMENT_SORT_FIELD2'] = 'ID';
$arParams['ELEMENT_SORT_ORDER2'] = 'desc';
break;
case 'set':
$arParams['ELEMENT_SORT_FIELD'] = 'property_KOMPLEKTNOST';
$arParams['ELEMENT_SORT_ORDER'] = 'desc,nulls';
$arParams['ELEMENT_SORT_FIELD2'] = 'name';
$arParams['ELEMENT_SORT_ORDER2'] = 'asc';
break;
case 'new':
default:
$arParams['ELEMENT_SORT_FIELD'] = 'property_NOVINKA';
$arParams['ELEMENT_SORT_ORDER'] = 'desc';
$arParams['ELEMENT_SORT_FIELD2'] = $sortPrice;
$arParams['ELEMENT_SORT_ORDER2'] = 'asc';
break;
}
$arResult['CURRENT_SORT'] = $currentSort;
html
<div class="sorting__box">
<form id="sortForm" action="<?=$APPLICATION->GetCurPage()?>" method="get" class="sorting-form">
<div class="sorting">
<div class="select__box sorting-box custom-select">
<select class="form-select" name="sort" onchange="submitFormSorting()">
<option value="new" <?=($arResult['CURRENT_SORT'] == 'new') ? 'selected' : ''?>>Новинки</option>
<option value="price_asc" <?=($arResult['CURRENT_SORT'] == 'price_asc') ? 'selected' : ''?>>По цене (возрастание)</option>
<option value="price_desc" <?=($arResult['CURRENT_SORT'] == 'price_desc') ? 'selected' : ''?>>По цене (убывание)</option>
<option value="set" <?=($arResult['CURRENT_SORT'] == 'set') ? 'selected' : ''?>>По гарнитуру</option>
</select>
</div>
</div>
<?php
// Сохраняем другие GET параметры
foreach ($_GET as $key => $value) {
if ($key !== 'sort' && $key !== 'sort_ajax') {
if (is_array($value)) {
foreach ($value as $item) {
echo '<input type="hidden" name="'.htmlspecialcharsbx($key).'[]" value="'.htmlspecialcharsbx($item).'">';
}
} else {
echo '<input type="hidden" name="'.htmlspecialcharsbx($key).'" value="'.htmlspecialcharsbx($value).'">';
}
}
}
?>
</form>
</div>
sections.php
В этом файле, для реализации обновления товаров без перезагрузки, нам нужном обрамить компонент catalog.section следующим кодом
<div class="catalog-products" id="catalogProducts">
<?
// Для сортировки
if ($_REQUEST['sort_ajax'] === 'Y') {
$APPLICATION->RestartBuffer();
}
?>
<? $APPLICATION->IncludeComponent(
"bitrix:catalog.section",
'section',
[
"IBLOCK_TYPE" => $arParams["IBLOCK_TYPE"],
"IBLOCK_ID" => $arParams["IBLOCK_ID"],
"ELEMENT_SORT_FIELD" => $arParams["ELEMENT_SORT_FIELD"],
"ELEMENT_SORT_ORDER" => $arParams["ELEMENT_SORT_ORDER"],
"ELEMENT_SORT_FIELD2" => $arParams["ELEMENT_SORT_FIELD2"],
"ELEMENT_SORT_ORDER2" => $arParams["ELEMENT_SORT_ORDER2"],
// ...
],
$component
);
?>
<?
// Сортировка
if ($_REQUEST['sort_ajax'] === 'Y') {
die();
}
?>
</div>
script.js
Добавляем обработчик на форму выбора сортировки.
/**
* Сортировка в каталоге (AJAX)
*/
function submitFormSorting() {
const form = document.getElementById('sortForm');
const select = form.querySelector('select[name="sort"]');
const selectedValue = select.value;
const cookieName = 'catalog_sort_order';
const catalogSectionBlock = document.querySelector('#catalogProducts');
// Сохраняем выбранную сортировку в cookie
// BX.setCookie(cookieName, selectedValue, {expires: 86400*365}); // 365 дней
BX.setCookie(cookieName, selectedValue, {expires: 57600, path: '/'}); // 16 часов
if (catalogSectionBlock) {
toggleLoader(catalogSectionBlock); // Показываем лоадер
const formData = new FormData();
formData.append('sort', selectedValue);
formData.append('sort_ajax', 'Y'); // Флаг AJAX-запроса
// Сохраняем другие параметры URL
const urlParams = new URLSearchParams(window.location.search);
for (const [key, value] of urlParams) {
if (key !== 'sort') {
formData.append(key, value);
}
}
fetch(window.location.href, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest' // Для обработки на сервере
}
})
.then(response => response.text())
.then(response => {
catalogSectionBlock.innerHTML = response;
// Обработка скриптов в ответе
const ob = BX.processHTML(response);
BX.ajax.processScripts(ob.SCRIPT);
// Генерируем кастомное событие
BX.onCustomEvent('onCatalogSortChanged', [{
block: catalogSectionBlock,
sortValue: selectedValue
}]);
toggleLoader(catalogSectionBlock, 'remove'); // Скрываем лоадер
})
.catch(error => {
toggleLoader(catalogSectionBlock, 'remove');
console.error('Sorting error:', error);
});
}
}
// Установка текущего значения при загрузке страницы
document.addEventListener('DOMContentLoaded', () => {
const cookieName = 'catalog_sort_order';
const cookieValue = document.cookie
.split('; ')
.find(row => row.startsWith(cookieName))
?.split('=')[1];
if (cookieValue) {
const select = document.querySelector('#sortForm select[name="sort"]');
if (select) {
select.value = cookieValue;
}
}
});