6

How can I remove Category Filter from Magento 2 Product List Page.

1
  • magento\vendor\magento\module-layered-navigation\view\frontend\layout\catalog_category_view_type_layered.xml & magento\vendor\magento\module-layered-navigation\view\frontend\templates\layer\view.phtml
    – Jackson
    Commented Dec 13, 2016 at 7:00

5 Answers 5

13

You have to override core file into your theme, Category layered navigation comes form core file,

vendor/magento/module-layered-navigation/view/frontend/templates/layer/view.phtml

You have to get files from core and keep in your theme,

app/design/frontend/{Vendor}}/{themename}}/Magento_LayeredNavigation/templates/layer/view.phtml

Now you can set condition for this,

<?php  if($filter->getName() != __('Category')) { } ?>

in code.

<?php

/**
 * Category layered navigation
 *
 * @var $block \Magento\LayeredNavigation\Block\Navigation
 */
?>
<?php if ($block->canShowBlock()): ?>
    <div class="block filter">
        <div class="block-title filter-title">
            <strong><?php /* @escapeNotVerified */ echo __('Shop By') ?></strong>
        </div>

        <div class="block-content filter-content">
            <?php echo $block->getChildHtml('state') ?>

            <?php if ($block->getLayer()->getState()->getFilters()): ?>
                <div class="block-actions filter-actions">
                    <a href="<?php /* @escapeNotVerified */ echo $block->getClearUrl() ?>" class="action clear filter-clear"><span><?php /* @escapeNotVerified */ echo __('Clear All') ?></span></a>
                </div>
            <?php endif; ?>
            <?php $wrapOptions = false; ?>
            <?php foreach ($block->getFilters() as $filter): ?>
                <?php if (!$wrapOptions): ?>
                    <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?php /* @escapeNotVerified */ echo __('Shopping Options') ?></strong>
                    <dl class="filter-options" id="narrow-by-list">
                <?php $wrapOptions = true; endif; ?>
                <?php  if($filter->getName() != __('Category')) { ?>
                    <?php if ($filter->getItemsCount()): ?>
                        <dt role="heading" aria-level="3" class="filter-options-title"><?php echo $block->escapeHtml(__($filter->getName())) ?></dt>
                        <dd class="filter-options-content"><?php /* @escapeNotVerified */ echo $block->getChildBlock('renderer')->render($filter); ?></dd>
                    <?php endif; ?>
                    <?php } ?>
            <?php endforeach; ?>
            <?php if ($wrapOptions): ?>
                </dl>
            <?php endif; ?>
        </div>
    </div>
<?php endif; ?>
3
  • 4
    The IF clause should actually be $filter->getName() != 'Category' since translating the string with _ would cause the filter to appear in other languages.
    – DreamWave
    Commented Jan 25, 2018 at 10:18
  • hi@Rakesh, this removes the category filter totally from layered navigation? if mannually we enter url will it work? Commented Jan 3, 2019 at 7:50
  • Could you pls explain, in which part add your condition? @Rakesh Jesadiya
    – zus
    Commented Aug 28, 2020 at 17:08
10

Better to use as:

<?php  
if($filter->getRequestVar() != 'cat') { 
    // ...
} 
?>
4
  • 1
    This should be the accepted answer
    – PY Yick
    Commented Jun 7, 2018 at 7:41
  • 1
    Where should update this line?
    – zus
    Commented Aug 28, 2020 at 17:07
  • 1
    Good Answer! working fine in m2.4.0 Commented Nov 24, 2020 at 12:30
  • 1
    This is a great answer, even if the language is diff, this works like magic. This should be an accepted answer.. Commented Jul 6, 2023 at 19:22
6

Since this is the top result in Google for my search "magento 2 remove category filter from layered navigation", and all the answers suggest entirely replacing a template file (which is subject to Theme-level discrepancies) I thought I'd provide an answer that does not involve a .phtml template replacement.

The Category filter can be removed from Layered Navigation "Shopping Options" list by using a Plugin.

In your module's etc/di.xml file, define the plugin and class DI properties:

    <type name="Magento\Catalog\Model\Layer\FilterList">
        <plugin name="remove_layered_nav_category_filter" type="Vendor\Module\Plugin\Catalog\Model\Layer\FilterList" sortOrder="1" disabled="false" />
    </type>

    <type name="Vendor\Module\Plugin\Catalog\Model\Layer\FilterList">
        <arguments>
            <argument name="categoryFilters" xsi:type="array">
                <item name="catalogsearch_category" xsi:type="string">Magento\CatalogSearch\Model\Layer\Filter\Category</item>
                <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Filter\Category</item>
            </argument>
        </arguments>
    </type>

And declare the Plugin class:

namespace Vendor\Module\Plugin\Catalog\Model\Layer;


class FilterList
{
    const CATALOG_CATEGORY_FILTER = 'category';
    const CATALOG_SEARCH_CATEGORY_FILTER = 'catalogsearch_category';

    /**
     * @var array
     */
    protected $categoryFilterTypes = [
        self::CATALOG_SEARCH_CATEGORY_FILTER => \Magento\CatalogSearch\Model\Layer\Filter\Category::class,
        self::CATALOG_CATEGORY_FILTER        => \Magento\Catalog\Model\Layer\Filter\Category::class
    ];

    /**
     * FilterList constructor.
     *
     * @param array $categoryFilters
     */
    public function __construct(array $categoryFilters)
    {
        $this->categoryFilterTypes = array_merge($this->categoryFilterTypes, $categoryFilters);
    }


    /**
     * Remove Category Filter from FilterList
     *
     * @param \Magento\Catalog\Model\Layer\FilterList $subject
     * @param                                         $result
     * @param \Magento\Catalog\Model\Layer            $layer
     * @return array
     */
    public function afterGetFilters(
        \Magento\Catalog\Model\Layer\FilterList $subject,
        $result,
        \Magento\Catalog\Model\Layer $layer
    ) {
        foreach ($result as $idx => $filter) {
            if ($this->isCategoryFilter($filter)) {
                unset($result[$idx]);
                break;
            }
        }

        return array_values($result);
    }

    /**
     * Determine if given Filter is one of the declared Category Filter types
     *
     * @param $filter
     * @return bool
     */
    private function isCategoryFilter($filter)
    {
        return \in_array(get_class($filter), $this->categoryFilterTypes);
    }
}

This leaves other Filters (e.g., Attribute, Price, Decimal) in place while removing any of the possible Category filters. Should additional Category filters be introduced, a simple change to DI configuration is all that is necessary to extend the functionality.

2
  • Thanks for this. I was also looking on a way how to do this without touching the phtml file. Seems harder than it should — I also tried to look for a way to do it in di.xml, but due to array item merging it seems you can't do that.
    – Erfan
    Commented Apr 1, 2020 at 14:28
  • 1
    Glad to help @Erfan and I agree, more involved than it should be!
    – John Hall
    Commented Apr 1, 2020 at 18:42
0

magento\vendor\magento\module-layered-navigation\view\frontend\layout\catalog_category_view_type_layered.xml orverride file

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <attribute name="class" value="page-with-filter"/>
        <referenceContainer name="sidebar.main">
            <block class="Magento\LayeredNavigation\Block\Navigation\Category" name="catalog.leftnav" before="-" template="layer/view.phtml">
                <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" />
                <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="layer/filter.phtml"/>
            </block>
        </referenceContainer>
    </body>
</page>

Remove Block

7
  • Hi @Ankit Shah, Actually We need filters only I need to exclude category (dropdown) filters.All other Attribute Filters Need.Category Is not attribute na to exclude that from filters.So How we exclude only that category filter. Commented Dec 13, 2016 at 7:04
  • What have u tried so far?
    – Jackson
    Commented Dec 13, 2016 at 7:06
  • I tried searching that category rendering phtml but all are coming in single array.So Just now find that model file to stop rendering that filters. Commented Dec 13, 2016 at 7:09
  • 2
    "magento\vendor\magento\module-catalog\Model\Layer\FilterList.php" This file we need to override and comment the 70,71,72 lines in our local file Commented Dec 13, 2016 at 7:19
  • 1
    Yes, Without touching model file we can stop it in phtml itself as our friend @Rakesh told :) Commented Dec 13, 2016 at 7:29
0

Sadly the fix from Rakesh is not working for me. The filter is not collapsible anymore. How can we still remove the categorie filter in our code? On default we have the filters collapsible.

<?php if ($block->canShowBlock()): ?>
<div class="block filter" id="layered-filter-block" data-mage-init='{"collapsible":{"openedState": "active", "collapsible": true, "active": false, "collateral": { "openedState": "filter-active", "element": "body" } }}'>
    <?php $filtered = count($block->getLayer()->getState()->getFilters()) ?>
    <div class="block-title filter-title" data-count="<?= /* @escapeNotVerified */ $filtered ?>">
        <strong data-role="title"><?= /* @escapeNotVerified */ __('Shop By') ?></strong>
    </div>
    <div class="block-content filter-content">
        <?= $block->getChildHtml('state') ?>

        <?php if ($block->getLayer()->getState()->getFilters()): ?>
            <div class="block-actions filter-actions">
                <a href="<?= /* @escapeNotVerified */ $block->getClearUrl() ?>" class="action clear filter-clear"><span><?= /* @escapeNotVerified */ __('Clear All') ?></span></a>
            </div>
        <?php endif; ?>
        <?php $wrapOptions = false; ?>
        <?php foreach ($block->getFilters() as $filter): ?>
            <?php if ($filter->getItemsCount()): ?>
                <?php if (!$wrapOptions): ?>
                    <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?= /* @escapeNotVerified */ __('Shopping Options') ?></strong>
                    <?php $range = implode(' ', range(0, $filter->getItemsCount())); ?>
                    <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init='{"accordion":{"openedState": "active", "collapsible": true, "active": "<?php echo $range; ?>", "multipleCollapsible": true}}'>
                <?php  $wrapOptions = true; endif; ?>
                <?php  if($filter->getName() != __('Category')) { } ?>
                <div data-role="collapsible" class="filter-options-item">
                    <div data-role="title" class="filter-options-title"><?= /* @escapeNotVerified */ __($filter->getName()) ?></div>
                    <div data-role="content" class="filter-options-content"><?= /* @escapeNotVerified */ $block->getChildBlock('renderer')->render($filter) ?></div>
                </div>
            <?php endif; ?>
        <?php endforeach; ?>
        <?php if ($wrapOptions): ?>
            </div>
        <?php else: ?>
            <script>
                require([
                    'jquery'
                ], function ($) {
                    $('#layered-filter-block').addClass('filter-no-options');
                });
            </script>
        <?php endif; ?>
    </div>
</div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.