Reading list Switch to dark mode

    How to create layered navigation on custom page in Magento 2?

    Updated 29 February 2024

    Today I’ll explain how you can add layered navigation to a custom page. In this example I’ll create a module named Webkul_LayeredNavigation and on layerednavigation/index/index page I’ll show the products with layered navigation.

    Here I’ll only explain those code which are necessary for implementation of the layered navigation.

    P.S – You can check Magento 2 Layered Navigation Extension

    First create di.xml with following code under Webkul/LayeredNavigation/etc/ folder,

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
        <preference for="Magento\Catalog\Model\Layer\ContextInterface" type="Magento\Catalog\Model\Layer\Context" />
        <preference for="Magento\Catalog\Model\Layer\ItemCollectionProviderInterface" type="Magento\Catalog\Model\Layer\Category\ItemCollectionProvider" />
        <preference for="Magento\Catalog\Model\Layer\StateKeyInterface" type="Magento\Catalog\Model\Layer\Category\StateKey" />
        <preference for="Magento\Catalog\Model\Layer\CollectionFilterInterface" type="Magento\Catalog\Model\Layer\Category\CollectionFilter" />
        <preference for="Magento\Catalog\Model\Layer\FilterableAttributeListInterface" type="Magento\Catalog\Model\Layer\Category\FilterableAttributeList" />
        <preference for="Magento\Catalog\Model\Layer\AvailabilityFlagInterface" type="Magento\Catalog\Model\Layer\Category\AvailabilityFlag" />
        <preference for="Magento\Catalog\Model\ResourceModel\Layer\Filter\Price" type="Webkul\LayeredNavigation\Model\ResourceModel\Layer\Filter\Price" />
    </config>

    Then add following in the layout file which in my case is layerednavigation_index_index.xml under Webkul/LayeredNavigation/view/frontend/layout/ folder,

    Searching for an experienced
    Magento 2 Company ?
    Find out More
    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    	<body>
            <attribute name="class" value="page-products"/>
            <referenceContainer name="content">
                <block class="Webkul\LayeredNavigation\Block\Product\ListProduct" name="layerednavigation_index_index" as="product_list" template="Magento_Catalog::product/list.phtml">
                    <container name="category.product.list.additional" as="additional" />
                    <block class="Magento\Framework\View\Element\RendererList" name="category.product.type.details.renderers" as="details.renderers">
                        <block class="Magento\Framework\View\Element\Template" name="category.product.type.details.renderers.default" as="default"/>
                    </block>
                    <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="category.product.addto" as="addto">
                        <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                            name="category.product.addto.compare" as="compare"
                            template="Magento_Catalog::product/list/addto/compare.phtml"/>
                    </block>
                    <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml">
                        <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/>
                    </block>
                    <action method="setToolbarBlockName">
                        <argument name="name" xsi:type="string">product_list_toolbar</argument>
                    </action>
                </block>
            </referenceContainer>
            <referenceContainer name="sidebar.main">
                <block class="Webkul\LayeredNavigation\Block\Navigation" name="catalog.leftnav" as="navigation" before="-" template="Magento_LayeredNavigation::layer/view.phtml">
                    <block class="Webkul\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" template="Magento_LayeredNavigation::layer/state.phtml" />
                    <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml">
                      <arguments>
                          <argument name="product_layer_view_model" xsi:type="object">Magento\LayeredNavigation\ViewModel\Layer\Filter</argument>
                      </arguments>
                    </block>
                </block>
            </referenceContainer>
            <referenceBlock name="layerednavigation_index_index">
                 <arguments>
                      <argument name="viewModel" xsi:type="object">Magento\Catalog\ViewModel\Product\OptionsData</argument>
                 </arguments>
            </referenceBlock>
        </body>
    </page>

    In the above code I have added class page-products to the body tag to inherit the default styling.

    Now we will override the model files to get required data.

    Now create Layer.php under Webkul/LayeredNavigation/Model/ folder with following code,

    <?php
    namespace Webkul\LayeredNavigation\Model;
    
    use Magento\Catalog\Api\CategoryRepositoryInterface;
    use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as AttributeCollectionFactory;
    use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
    
    class Layer extends \Magento\Catalog\Model\Layer
    {
        public function __construct(
            \Magento\Catalog\Model\Layer\ContextInterface $context,
            \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory,
            AttributeCollectionFactory $attributeCollectionFactory,
            \Magento\Catalog\Model\ResourceModel\Product $catalogProduct,
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            \Magento\Framework\Registry $registry,
            CategoryRepositoryInterface $categoryRepository,
            CollectionFactory $productCollectionFactory,
            array $data = []
        ) {
            $this->productCollectionFactory = $productCollectionFactory;
            parent::__construct(
                $context,
                $layerStateFactory,
                $attributeCollectionFactory,
                $catalogProduct,
                $storeManager,
                $registry,
                $categoryRepository,
                $data
            );
        }
    
    	public function getProductCollection()
    	{
            if (isset($this->_productCollections['webkul_custom'])) {
                $collection = $this->_productCollections['webkul_custom'];
            } else {
                //here you assign your own custom collection of products
                $collection = $this->productCollectionFactory->create();
                $this->prepareProductCollection($collection);
                $this->_productCollections['webkul_custom'] = $collection;
            }
    		return $collection;
    	}
    
    }

    After that create Resolver.php under Webkul/LayeredNavigation/Model/Layer/ folder with following code,

    <?php
    namespace Webkul\LayeredNavigation\Model\Layer;
    
    class Resolver extends \Magento\Catalog\Model\Layer\Resolver
    {
    	public function __construct(
    		\Magento\Framework\ObjectManagerInterface $objectManager,
    		\Webkul\LayeredNavigation\Model\Layer $layer,
    		array $layersPool
    	) {
    		$this->layer = $layer;
    		parent::__construct($objectManager, $layersPool);
    	}
    
    	public function create($layerType)
    	{
    		
    	}
    }

    Then under Webkul/LayeredNavigation/Model/ResourceModel/Layer/Filter/ folder create Price.php file,

    <?php
    namespace Webkul\LayeredNavigation\Model\ResourceModel\Layer\Filter;
    
    use Magento\Framework\App\Http\Context;
    use Magento\Framework\Indexer\DimensionFactory;
    use Magento\Framework\Search\Request\IndexScopeResolverInterface;
    
    class Price extends \Magento\Catalog\Model\ResourceModel\Layer\Filter\Price 
    {
        public function __construct(
            \Magento\Framework\Model\ResourceModel\Db\Context $context,
            \Magento\Framework\Event\ManagerInterface $eventManager,
            \Webkul\LayeredNavigation\Model\Layer\Resolver $layerResolver,
            \Magento\Customer\Model\Session $session,
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            $connectionName = null,
            IndexScopeResolverInterface $priceTableResolver = null,
            Context $httpContext = null,
            DimensionFactory $dimensionFactory = null
        ) {
            parent::__construct($context, $eventManager, $layerResolver, $session, $storeManager, $connectionName, $priceTableResolver, $httpContext, $dimensionFactory);
        }
    }

    Now we are done with the model and we will override the block to show proper data.

    Now create Navigation.php file under Webkul/LayeredNavigation/Block/ folder with following content,

    <?php
    namespace Webkul\LayeredNavigation\Block;
    
    class Navigation extends \Magento\LayeredNavigation\Block\Navigation
    {
    	public function __construct(
    		\Magento\Framework\View\Element\Template\Context $context,
    		\Webkul\LayeredNavigation\Model\Layer\Resolver $layerResolver,
    		\Magento\Catalog\Model\Layer\FilterList $filterList,
    		\Magento\Catalog\Model\Layer\AvailabilityFlagInterface $visibilityFlag,
    		array $data = []
    	) {
    		parent::__construct($context, $layerResolver, $filterList,
    			$visibilityFlag);
    	}
    }

    Then create State.php file under Webkul/LayeredNavigation/Block/Navigation/ folder with following code,

    <?php
    namespace Webkul\LayeredNavigation\Block\Navigation;
    
    class State extends \Magento\LayeredNavigation\Block\Navigation\State
    {
        public function __construct(
            \Magento\Framework\View\Element\Template\Context $context,
            \Webkul\LayeredNavigation\Model\Layer\Resolver $layerResolver,
            array $data = []
        ) {
            parent::__construct($context, $layerResolver, $data);
    }
    }

    Then under Webkul/LayeredNavigation/Block/Product/ folder create ListProduct.php and add following code,

    <?php
    namespace Webkul\LayeredNavigation\Block\Product;
    
    class ListProduct extends \Magento\Catalog\Block\Product\ListProduct
    {
    	public function __construct(
    		\Magento\Catalog\Block\Product\Context $context,
    		\Magento\Framework\Data\Helper\PostHelper $postDataHelper,
    		\Webkul\LayeredNavigation\Model\Layer\Resolver $layerResolver,
    		\Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository,
    		\Magento\Framework\Url\Helper\Data $urlHelper,
    		array $data = []
    	) {
    		parent::__construct($context, $postDataHelper, $layerResolver,
    			$categoryRepository, $urlHelper, $data);
    	}
    }

    That’s it, we have overridden all the required files.

    Now you can check the front-end and it should display the layered navigation on left side,

    Custom page showing layered navigation

    Happy coding 🙂

    . . .

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    8 comments

  • Jhonattan
  • Moses
    • Sanjay Chouhan (Moderator)
  • sebastien
    • Sanjay Chouhan (Moderator)
  • birjitsinh
  • Navin Bhudiya
    • Sanjay Chouhan (Moderator)
  • Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home