Magento 2 Layout – Change Category Layout Based on Category Level

categorylayoutmagento-2.1magento2xml

I have a lot of categories with different levels (parent/child structure) and I want to implement different design/structure of each level category.

Suppose I have these categories

=> Category A (first Level)

=>=> Category B (Second level)

=>=>=> Category C (third level)

=>=>=>=> Category D (fourth level)

I have two solutions

  1. Create a xml file catalog_category_view_id_{{id}}.xml

    Issue: I can't implement because I have many categories and it will be difficult to update in futures

  2. Change the category page layout of each category

    Issue: It’s not working because I think, I have already updated catalog_catalog_view.xml in my theme or its Magento bug

Please guide me about some better solution

Best Answer

One option would be adding a layout handle based on the category depth with an observer on the layout_load_before event. That would allow layout updates based on category depth using an xml file like catalog_category_view_level_{{level}}.xml

Vendor/Module/etc/frontend/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="layout_load_before">
        <observer name="vendor_module_layout_load_before" instance="Vendor\Module\Observer\CategoryDepthLayout" />
    </event>
</config>

Vendor/Module/Observer/CategoryDepthLayout.php

<?php

namespace Vendor\Module\Observer;

use Magento\Framework\Registry;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;

class CategoryDepthLayout implements ObserverInterface
{
    const ACTION_NAME = 'catalog_category_view';

    /** @var Registry */
    private $registry;

    public function __construct(
        Registry $registry
    ) {
        $this->registry = $registry;
    }

    public function execute(Observer $observer)
    {
        if ($observer->getFullActionName() !== self::ACTION_NAME) {
            return;
        }

        $category = $this->registry->registry('current_category');

        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $observer->getLayout();
        $layout->getUpdate()->addHandle(self::ACTION_NAME . '_level_' . $category->getLevel());
    }
}

I tested this real quick by adding the following layout file removing breadcrumbs from level 2 categories:

Vendor/Module/view/frontend/layout/catalog_category_view_level_2.xml

<?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>
        <referenceBlock name="breadcrumbs" remove="true" />
    </body>
</page>
Related Topic