2

I have a category with id =41 and have 2 child i want to see the parent category and her child but just make the parent category link not cliquable any idea please and thanks in advance

3

You need to create a custom module to override Template.php. See below for the module. One should not make changes in the vendor directory.

app/code/[vendor]/[module]/Block/Html/Topmenu.php

<?php
namespace [vendor]\[module]\Block\Html;

use Magento\Framework\Data\Tree\Node;
use Magento\Framework\Data\Tree\NodeFactory;
use Magento\Framework\Data\TreeFactory;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\View\Element\Template;

/**
* Html page top menu block
*
* @api
* @since 100.0.2
*/
class Topmenu extends Template implements IdentityInterface
{
/**
 * Cache identities
 *
 * @var array
 */
protected $identities = [];

/**
 * Top menu data tree
 *
 * @var \Magento\Framework\Data\Tree\Node
 */
protected $_menu;

/**
 * @var NodeFactory
 */
private $nodeFactory;

/**
 * @var TreeFactory
 */
private $treeFactory;

/**
 * @param Template\Context $context
 * @param NodeFactory $nodeFactory
 * @param TreeFactory $treeFactory
 * @param array $data
 */
public function __construct(
    Template\Context $context,
    NodeFactory $nodeFactory,
    TreeFactory $treeFactory,
    array $data = []
) {
    parent::__construct($context, $data);
    $this->nodeFactory = $nodeFactory;
    $this->treeFactory = $treeFactory;
}

/**
 * Get block cache life time
 *
 * @return int
 * @since 100.1.0
 */
protected function getCacheLifetime()
{
    return parent::getCacheLifetime() ?: 3600;
}

/**
 * Get top menu html
 *
 * @param string $outermostClass
 * @param string $childrenWrapClass
 * @param int $limit
 * @return string
 */
public function getHtml($outermostClass = '', $childrenWrapClass = '', $limit = 0)
{
    $this->_eventManager->dispatch(
        'page_block_html_topmenu_gethtml_before',
        ['menu' => $this->getMenu(), 'block' => $this, 'request' => $this->getRequest()]
    );

    $this->getMenu()->setOutermostClass($outermostClass);
    $this->getMenu()->setChildrenWrapClass($childrenWrapClass);

    $html = $this->_getHtml($this->getMenu(), $childrenWrapClass, $limit);

    $transportObject = new \Magento\Framework\DataObject(['html' => $html]);
    $this->_eventManager->dispatch(
        'page_block_html_topmenu_gethtml_after',
        ['menu' => $this->getMenu(), 'transportObject' => $transportObject]
    );
    $html = $transportObject->getHtml();
    return $html;
}

/**
 * Count All Subnavigation Items
 *
 * @param \Magento\Backend\Model\Menu $items
 * @return int
 */
protected function _countItems($items)
{
    $total = $items->count();
    foreach ($items as $item) {
        /** @var $item \Magento\Backend\Model\Menu\Item */
        if ($item->hasChildren()) {
            $total += $this->_countItems($item->getChildren());
        }
    }
    return $total;
}

/**
 * Building Array with Column Brake Stops
 *
 * @param \Magento\Backend\Model\Menu $items
 * @param int $limit
 * @return array|void
 *
 * @todo: Add Depth Level limit, and better logic for columns
 */
protected function _columnBrake($items, $limit)
{
    $total = $this->_countItems($items);
    if ($total <= $limit) {
        return;
    }

    $result[] = ['total' => $total, 'max' => (int)ceil($total / ceil($total / $limit))];

    $count = 0;
    $firstCol = true;

    foreach ($items as $item) {
        $place = $this->_countItems($item->getChildren()) + 1;
        $count += $place;

        if ($place >= $limit) {
            $colbrake = !$firstCol;
            $count = 0;
        } elseif ($count >= $limit) {
            $colbrake = !$firstCol;
            $count = $place;
        } else {
            $colbrake = false;
        }

        $result[] = ['place' => $place, 'colbrake' => $colbrake];

        $firstCol = false;
    }

    return $result;
}

/**
 * Add sub menu HTML code for current menu item
 *
 * @param \Magento\Framework\Data\Tree\Node $child
 * @param string $childLevel
 * @param string $childrenWrapClass
 * @param int $limit
 * @return string HTML code
 */
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
{
    $html = '';
    if (!$child->hasChildren()) {
        return $html;
    }

    $colStops = [];
    if ($childLevel == 0 && $limit) {
        $colStops = $this->_columnBrake($child->getChildren(), $limit);
    }

    $html .= '<ul class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
    $html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
    $html .= '</ul>';

    return $html;
}

/**
 * Recursively generates top menu html from data that is specified in $menuTree
 *
 * @param \Magento\Framework\Data\Tree\Node $menuTree
 * @param string $childrenWrapClass
 * @param int $limit
 * @param array $colBrakes
 * @return string
 *
 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
 * @SuppressWarnings(PHPMD.NPathComplexity)
 */
protected function _getHtml(
    \Magento\Framework\Data\Tree\Node $menuTree,
    $childrenWrapClass,
    $limit,
    $colBrakes = []
) {
    $html = '';

    $children = $menuTree->getChildren();
    $parentLevel = $menuTree->getLevel();
    $childLevel = $parentLevel === null ? 0 : $parentLevel + 1;

    $counter = 1;
    $itemPosition = 1;
    $childrenCount = $children->count();

    $parentPositionClass = $menuTree->getPositionClass();
    $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';

    foreach ($children as $child) {
        $child->setLevel($childLevel);
        $child->setIsFirst($counter == 1);
        $child->setIsLast($counter == $childrenCount);
        $child->setPositionClass($itemPositionClassPrefix . $counter);

        $outermostClassCode = '';
        $outermostClass = $menuTree->getOutermostClass();

        if ($childLevel == 0 && $outermostClass) {
            $outermostClassCode = ' class="' . $outermostClass . '" ';
            $child->setClass($outermostClass);
        }

        if (count($colBrakes) && $colBrakes[$counter]['colbrake']) {
            $html .= '</ul></li><li class="column"><ul>';
        }

        $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
        if($child->getId() != 'category-node-41'){
            $html .= '<a data-test="'.$child->getLevel().'" href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>'
                . $this->escapeHtml($child->getName())
                . '</span></a>' . $this->_addSubMenu(
                    $child,
                    $childLevel,
                    $childrenWrapClass,
                    $limit
                ) . '</li>';
        }else{
            $html .= '<a href="javascript&colon;void(0)" ' . $outermostClassCode . '><span>'
                . $this->escapeHtml($child->getName())
                . '</span></a>' . $this->_addSubMenu(
                    $child,
                    $childLevel,
                    $childrenWrapClass,
                    $limit
                ) . '</li>';
        }
        $itemPosition++;
        $counter++;
    }

    if (count($colBrakes) && $limit) {
        $html = '<li class="column"><ul>' . $html . '</ul></li>';
    }

    return $html;
}

/**
 * Generates string with all attributes that should be present in menu item element
 *
 * @param \Magento\Framework\Data\Tree\Node $item
 * @return string
 */
protected function _getRenderedMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
    $html = '';
    $attributes = $this->_getMenuItemAttributes($item);
    foreach ($attributes as $attributeName => $attributeValue) {
        $html .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"';
    }
    return $html;
}

/**
 * Returns array of menu item's attributes
 *
 * @param \Magento\Framework\Data\Tree\Node $item
 * @return array
 */
protected function _getMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
    $menuItemClasses = $this->_getMenuItemClasses($item);
    return ['class' => implode(' ', $menuItemClasses)];
}

/**
 * Returns array of menu item's classes
 *
 * @param \Magento\Framework\Data\Tree\Node $item
 * @return array
 */
protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item)
{
    $classes = [];

    $classes[] = 'level' . $item->getLevel();
    $classes[] = $item->getPositionClass();

    if ($item->getIsCategory()) {
        $classes[] = 'category-item';
    }

    if ($item->getIsFirst()) {
        $classes[] = 'first';
    }

    if ($item->getIsActive()) {
        $classes[] = 'active';
    } elseif ($item->getHasActive()) {
        $classes[] = 'has-active';
    }

    if ($item->getIsLast()) {
        $classes[] = 'last';
    }

    if ($item->getClass()) {
        $classes[] = $item->getClass();
    }

    if ($item->hasChildren()) {
        $classes[] = 'parent';
    }

    return $classes;
}

/**
 * Add identity
 *
 * @param string|array $identity
 * @return void
 */
public function addIdentity($identity)
{
    if (!in_array($identity, $this->identities)) {
        $this->identities[] = $identity;
    }
}

/**
 * Get identities
 *
 * @return array
 */
public function getIdentities()
{
    return $this->identities;
}

/**
 * Get cache key informative items
 *
 * @return array
 * @since 100.1.0
 */
public function getCacheKeyInfo()
{
    $keyInfo = parent::getCacheKeyInfo();
    $keyInfo[] = $this->getUrl('*/*/*', ['_current' => true, '_query' => '']);
    return $keyInfo;
}

/**
 * Get tags array for saving cache
 *
 * @return array
 * @since 100.1.0
 */
protected function getCacheTags()
{
    return array_merge(parent::getCacheTags(), $this->getIdentities());
}

/**
 * Get menu object.
 *
 * Creates \Magento\Framework\Data\Tree\Node root node object.
 * The creation logic was moved from class constructor into separate method.
 *
 * @return Node
 * @since 100.1.0
 */
public function getMenu()
{
    if (!$this->_menu) {
        $this->_menu = $this->nodeFactory->create(
            [
                'data' => [],
                'idField' => 'root',
                'tree' => $this->treeFactory->create()
            ]
        );
    }
    return $this->_menu;
}
}

app/code/[vendor]/[module]/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="[vendor]_[module]" setup_version="1.0.0"/>
</config>

app/code/[vendor]/[module]/etc/di.xml

<?xml version="1.0" encoding="UTF-8"?> 
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> 
    <preference for="Magento\Theme\Block\Html\Topmenu" type="[vendor]\[module]\Block\Html\Topmenu" /> 
</config>

app/code/[vendor]/[module]/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '[vendor]_[module]',
    __DIR__
);
1

Override vendor/magento/module-theme/Block/Html/Topmenu.php in your custom module.

Take a look at this https://community.magento.com/t5/Magento-2-x-Programming/Remove-links-to-top-categories-in-menu/m-p/77074#M2904

It's the same code. Just change the if condition. For me category id is 20 so if($child->getId() != 'category-node-20'){...}. Place your category id instead of 20

vendor/magento/module-theme/Block/Html/Topmenu.php

protected function _getHtml(
        \Magento\Framework\Data\Tree\Node $menuTree,
        $childrenWrapClass,
        $limit,
        $colBrakes = []
    ) {
        $html = '';

        $children = $menuTree->getChildren();
        $parentLevel = $menuTree->getLevel();
        $childLevel = $parentLevel === null ? 0 : $parentLevel + 1;

        $counter = 1;
        $itemPosition = 1;
        $childrenCount = $children->count();

        $parentPositionClass = $menuTree->getPositionClass();
        $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';

        foreach ($children as $child) {
            $child->setLevel($childLevel);
            $child->setIsFirst($counter == 1);
            $child->setIsLast($counter == $childrenCount);
            $child->setPositionClass($itemPositionClassPrefix . $counter);

            $outermostClassCode = '';
            $outermostClass = $menuTree->getOutermostClass();

            if ($childLevel == 0 && $outermostClass) {
                $outermostClassCode = ' class="' . $outermostClass . '" ';
                $child->setClass($outermostClass);
            }

            if (count($colBrakes) && $colBrakes[$counter]['colbrake']) {
                $html .= '</ul></li><li class="column"><ul>';
            }

            $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
            if($child->getId() != 'category-node-20'){
            $html .= '<a data-test="'.$child->getLevel().'" href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>'
                . $this->escapeHtml($child->getName())
                . '</span></a>' . $this->_addSubMenu(
                    $child,
                    $childLevel,
                    $childrenWrapClass,
                    $limit
                ) . '</li>';
            }else{
            $html .= '<a href="javascript&colon;void(0)" ' . $outermostClassCode . '><span>'
                . $this->escapeHtml($child->getName())
                . '</span></a>' . $this->_addSubMenu(
                    $child,
                    $childLevel,
                    $childrenWrapClass,
                    $limit
                ) . '</li>';
            }
            $itemPosition++;
            $counter++;
        }

        if (count($colBrakes) && $limit) {
            $html = '<li class="column"><ul>' . $html . '</ul></li>';
        }

        return $html;
    }
  • ok thanks a lot i will check this solution :) – Developper Magento Feb 14 at 14:53
  • 1
    Ok. And as @MartinE is saying changing core files is not a good idea. I thought you already knew so just posted solution for your problem. – Vky Feb 14 at 15:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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