Request Quote

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.

 

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,

 

I have uploaded the all the code on Github. Follow this link to get the module https://github.com/sanjaychouhan-webkul/layered-navigation

Happy coding 🙂

. . .

Comments (4)

Add Your Comment

  • 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
      Please let me know which version of Magento are you using?
  • css.php
    Hire Us!
    Brief us about your requirements and we'll get back to you.
    Woo! Hooy!
    We have just recieved your project brief and our expert will contact you shortly.
    Send Again
    Close