Add custom css class to each item in Topmenu - Magento 2
-
02-01-2021 - |
Question
I'm looking for a way to add a custom css class to each menu item into the Topmenu.
I already tried to it using interceptor method in Topmenu
public function beforeGetHtml(
\Magento\Theme\Block\Html\Topmenu $subject,
$outermostClass = '',
$childrenWrapClass = '',
$limit = 0
) {
$rootId = $this->storeManager->getStore()->getRootCategoryId();
$storeId = $this->storeManager->getStore()->getId();
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $this->getCategoryTree($storeId, $rootId);
$currentCategory = $this->getCurrentCategory();
$mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion
foreach ($collection as $category) {
if (!isset($mapping[$category->getParentId()])) {
continue;
}
/** @var Node $parentCategoryNode */
$parentCategoryNode = $mapping[$category->getParentId()];
$categoryNode = new Node(
$this->getCategoryAsArray($category, $currentCategory),
'id',
$parentCategoryNode->getTree(),
$parentCategoryNode
);
$parentCategoryNode->addChild($categoryNode);
$mapping[$category->getId()] = $categoryNode; //add node in stack
}
}
and then:
private function getCategoryAsArray($category, $currentCategory)
{
return [
'name' => $category->getName(),
'id' => 'category-node-' . $category->getId(),
'class' => 'MY_CUSTOM_CLASS',
'url' => $this->catalogCategory->getCategoryUrl($category),
'has_active' => in_array((string)$category->getId(), explode('/', $currentCategory->getPath()), true),
'is_active' => $category->getId() == $currentCategory->getId()
];
}
However the classes are added only to submenu items instead of add to parent as well.
Thank you!
Solution
Try following code:
- app/code/[VendorName]/[ModuleName]/registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'[VendorName]_[ModuleName]',
__DIR__
);
- app/code/[VendorName]/[ModuleName]/etc/module.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="[VendorName]_[ModuleName]" setup_version="1.0.0">
<sequence>
<module name="Magento_Theme" />
</sequence>
</module>
</config>
- app/code/[VendorName]/[ModuleName]/etc/di.xml
<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="[VendorName]\[ModuleName]\Block\Html\Topmenu" />
</config>
- app/code/[VendorName]/[ModuleName]/Block/Html/Topmenu.php
<?php
namespace [VendorName]\[ModuleName]\Block\Html;
class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item)
{
$classes = [];
$classes[] = 'level' . $item->getLevel();
$classes[] = $item->getPositionClass();
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';
}
$classes[] = 'MY_CUSTOM_CLASS';
return $classes;
}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange