Menu Close
    Convert your store into Magento 2 Multi Vendor Marketplace

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

    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 Webkul Layered Navigation Module

    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,

    <?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"/>
                </block>
            </referenceContainer>
        </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 🙂

    . . .
    Discuss on Helpdesk

    Leave a Comment

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


    8 comments

  • Jhonattan
    Hi!
    This is very useful!
    I’m having an issue with price filter on this custom layered navigation. Query is broken when I activate filtering by price. I see magento’s ORM is mixing wrong tables. Take a look this pastebin https://pastebin.com/3RCb3Byj
    Any help will be appreciated.
    Thanks!
  • Moses
    Thank you for sharing this code. Its working perfect.
    I do have a question though, Does the Class Preferences that you have declared in the di.xml is safe. Any Idea why this is not declared by Magento itself.
    • Sanjay Chouhan (Moderator)
      Yes it is safe.
  • sebastien
    Hi,
    Can you tell me which version you use ?
    I’m trying on 2.1.9 but when I use the ‘setup:d:compile’ command it gives error :

    Class Magento\Framework\Indexer\DimensionFactory does not exist (use in the Price.php)

    This class doesn’t exists in 2.1.9
    Thanks for your help.

    • Sanjay Chouhan (Moderator)
      Hi, just remove it from the constructor.
  • birjitsinh
    please help me not working with 2.2.5
  • Navin Bhudiya
    it gives error
    : Uncaught Error: Call to a member function getIdentities() on null in vendor/magento/module-catalog/Block/Category/View.php:179
    • Sanjay Chouhan (Moderator)
      Please let me know which version of Magento are you using?
  • Back to Top