The question:
Is it possible to apply sorting option and direction at the same time, using sorting select box?
The sorting select box could have options like:
- Price Asc
- Price Desc
- Position Asc
- Position Desc
- ..
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
You can follow the steps describe below to achieve this customization task.
I assume you are using a custom theme “Vendor_theme” .
step 1) create the file sorter.phtml
under
/app/design/frontend/Vendor/theme/Magento_Catalog/templates/product/list/toolbar
File : sorter.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/**
* Product list toolbar
*
* @var $block MagentoCatalogBlockProductProductListToolbar
*/
use MagentoCatalogModelProductProductListToolbar;
$currentDirection = $block->getCurrentDirection();
?>
<div class="toolbar-sorter sorter">
<label class="sorter-label" for="sorter"><?= /* @escapeNotVerified */ __('Sort By') ?></label>
<select id="sorter" data-role="sorter" class="sorter-options">
<?php foreach ($block->getAvailableOrders() as $_key => $_order): ?>
<option value="<?= /* @escapeNotVerified */ $_key ?>&asc"
<?php if ($block->isOrderCurrent($_key) && ($block->getCurrentDirection()=='asc' || $block->getCurrentDirection()=='' )): ?>
selected="selected"
<?php endif; ?>
>
<?= $block->escapeHtml(__($_order)) ?> [ Asc ]
</option>
<option value="<?= /* @escapeNotVerified */ $_key ?>&desc"
<?php if ($block->isOrderCurrent($_key) && $block->getCurrentDirection()=='desc'): ?>
selected="selected"
<?php endif; ?>
>
<?= $block->escapeHtml(__($_order)) ?> [ Desc ]
</option>
<?php endforeach; ?>
</select>
<?php if ($block->getCurrentDirection() == 'desc'): ?>
<a title="<?= /* @escapeNotVerified */ __('Set Ascending Direction') ?>" href="#" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" class="action sorter-action sort-desc" data-role="direction-switcher" data-value="asc">
<span><?= /* @escapeNotVerified */ __('Set Ascending Direction') ?></span>
</a>
<?php else: ?>
<a title="<?= /* @escapeNotVerified */ __('Set Descending Direction') ?>" href="#" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" class="action sorter-action sort-asc" data-role="direction-switcher" data-value="desc">
<span><?= /* @escapeNotVerified */ __('Set Descending Direction') ?></span>
</a>
<?php endif; ?>
</div>
step 2: create the file requirejs-config.js
under
/app/design/frontend/Vendor/theme/Magento_Catalog
File : requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/product/list/toolbar': {'Magento_Catalog/js/product/list/toolbar-mixin': true},
},
}
};
step 3: create the file toolbar-mixin.js
under
/app/design/frontend/Vendor/theme/Magento_Catalog/web/js/product/list
File: toolbar-mixin.js
define([
'jquery',
'uiComponent'
], function($, Component) {
'use strict';
return function(target) {
return $.widget('mage.productListToolbarForm', $.mage.productListToolbarForm, {
_processSelect: function (event) {
var optionvalue = event.currentTarget.options[event.currentTarget.selectedIndex].value;
var optionvalueParts = optionvalue.split("&");
this.mychangeUrl(
event.data.paramName,
optionvalueParts[0],
event.data.default,
optionvalueParts[1]
);
},
mychangeUrl: function (paramName, paramValue, defaultValue,listdir) {
var decode = window.decodeURIComponent,
urlPaths = this.options.url.split('?'),
baseUrl = urlPaths[0],
urlParams = urlPaths[1] ? urlPaths[1].split('&') : [],
paramData = {},
parameters, i;
for (i = 0; i < urlParams.length; i++) {
parameters = urlParams[i].split('=');
paramData[decode(parameters[0])] = parameters[1] !== undefined ?
decode(parameters[1].replace(/+/g, '%20')) :
'';
}
paramData[paramName] = paramValue;
console.log(paramData);
if (paramValue == defaultValue) { //eslint-disable-line eqeqeq
delete paramData[paramName];
}
delete paramData['product_list_dir'];
paramData = $.param(paramData);
baseUrl = baseUrl + (paramData.length ? '?' + paramData : '');
baseUrl = baseUrl + (paramData.length ? '&' + 'product_list_dir='+listdir : '?' + 'product_list_dir='+listdir);
baseUrl= decodeURIComponent( baseUrl.replace(/+/g, '%20'));
location.href = baseUrl;
},
});
}
});
step 4:: Run below commadn from Magento root to remove static files and cache.
sudo rm -rf var/view_preprocessed/*
sudo rm -rf var/pub/static/*
sudo rm -rf var/cache/*
sudo rm -rf var/generated
sudo rm -rf var/composer_home
sudo rm -rf var/page_cache
sudo rm -rf var/view_preprocessed
sudo rm -rf pub/static/frontend/*
Method 2
Create a module with name STech_Sortby by following below steps:
Step 1: Create registration.php under
app/code/STech/Sortby/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'STech_Sortby',
__DIR__
);
Step 2: Create module.xml under
app/code/STech/Sortby/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="STech_Sortby" setup_version="0.0.1">
<sequence>
<module name="Magento_Catalog"/>
</sequence>
</module>
</config>
Step 3: Create di.xml under
app/code/STech/Sortby/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoCatalogBlockProductProductListToolbar">
<plugin name="custom_block_toolbar" type="STechSortbyPluginCatalogBlockToolbar" />
</type>
<type name="MagentoCatalogModelConfig">
<plugin name="custom_catalog_model_config" type="STechSortbyPluginCatalogModelConfig" />
</type>
</config>
Step 4: Create Toolbar.php under
app/code/STech/Sortby/Plugin/Catalog/Block/Toolbar.php
<?php
namespace STechSortbyPluginCatalogBlock;
class Toolbar
{
public function aroundSetCollection(
MagentoCatalogBlockProductProductListToolbar $subject,
Closure $proceed,
$collection
) {
$currentOrder = $subject->getCurrentOrder();
$result = $proceed($collection);
if ($currentOrder) {
if ($currentOrder == 'price_desc') {
$subject->getCollection()->setOrder('price', 'desc');
} elseif ($currentOrder == 'price_asc') {
$subject->getCollection()->setOrder('price', 'asc');
} elseif ($currentOrder == 'position_asc') {
$subject->getCollection()->addAttributeToSort('position', 'asc')->addAttributeToSort('entity_id', 'asc');
} elseif ($currentOrder == 'position_desc') {
$subject->getCollection()->addAttributeToSort('position', 'desc')->addAttributeToSort('entity_id', 'desc');
}
}
return $result;
}
}
Step 5: Create Config.php under
app/code/STech/Sortby/Plugin/Catalog/Model/Config.php
<?php
namespace STechSortbyPluginCatalogModel;
class Config
{
public function afterGetAttributeUsedForSortByArray(
MagentoCatalogModelConfig $catalogConfig,
$options
) {
unset($options['position']);
unset($options['price']);
$options['price_asc'] = __('Price Asc');
$options['price_desc'] = __('Price Desc');
$options['position_asc'] = __('Position Asc');
$options['position_desc'] = __('Position Desc');
return $options;
}
}
Thats it!. Now run setup upgrade and other required commands and check.
Method 3
This can be done using Magento2 Plugins.
check this one:
Create the following files in your module: (Assuming you have your own module registered already)
Create your Plugin under Vendor/Modulename/etc/di.xml
di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoCatalogModelConfig">
<plugin name="Vendor_Modulename::addCustomOptions" type="VendorModulenamePluginModelConfig" />
</type>
<type name="MagentoCatalogBlockProductProductListToolbar">
<plugin name="Vendor::addPriceDescendingFilterInToolbar" type="VendorModulenamePluginProductProductListToolbar" />
</type>
Then create a config.php under namespace Vendor/Modulename/Plugin/Model/Config.php
and put this code:
<?php
namespace VendorModulenamePluginModel;
use MagentoStoreModelStoreManagerInterface;
class Config {
protected $_storeManager;
public function __construct(
StoreManagerInterface $storeManager
) {
$this->_storeManager = $storeManager;
}
public function afterGetAttributeUsedForSortByArray(MagentoCatalogModelConfig $catalogConfig, $options)
{
$store = $this->_storeManager->getStore();
$currencySymbol = $store->getCurrentCurrency()->getCurrencySymbol();
// Remove specific default sorting options
$default_options = [];
$default_options['name'] = $options['name'];
//New sorting options
$customOption['price_asc'] = __( ' Price ascending' );
//Merge default sorting options with custom options
$options = array_merge($customOption, $options);
return $options;
}
}
Then override the Toolbar.php ***Vendor/Modulename/Plugin/Product/ProductList/Toolbar.php
use this code
<?php
namespace VendorModulenamePluginProductProductList;
class Toolbar
{
public function aroundSetCollection(
MagentoCatalogBlockProductProductListToolbar $subject,
Closure $proceed,
$collection
) {
$currentOrder = $subject->getCurrentOrder();
$result = $proceed($collection);
if ($currentOrder) {
if ($currentOrder == 'price_asc') {
$subject->getCollection()->setOrder('price', 'asc');
}
}
return $result;
}
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0