Magento 2 - add link with content to top menu
-
29-12-2020 - |
Solução
You can add elements to the top menu using the event page_block_html_topmenu_gethtml_before.
Step 1 - So you need to create a module with these files (all the files should be in app/code/[Namespace]/[Module]):
Step 2 - app/code/[Namespace]/[Module]/etc/module.xml - the module declaration file
<?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="[Namespace]_[Module]" setup_version="2.0.0">
<sequence>
<module name="Magento_Theme"/>
</sequence>
</module>
</config>
Step 3 - app/code/[Namespace]/[Module]/registration.php - the registration file
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'[Namespace]_[Module]',
__DIR__
);
Step 4 - app/code/[Namespace]/[Module]/etc/frontend/events.xml - the events declaration file
<?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="page_block_html_topmenu_gethtml_before">
<observer name="[namespace]_[module]_observer" instance="[Namespace]\[Module]\Observer\Topmenu" />
</event>
</config>
Step 5 - app/code/[Namespace]/[Module]/Observer/Topmenu.php - the actual observer
<?php
namespace [Namespace]\[Module]\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Data\Tree\Node;
use Magento\Framework\Event\ObserverInterface;
class Topmenu implements ObserverInterface
{
public function __construct(
...//add dependencies here if needed
)
{
...
}
/**
* @param EventObserver $observer
* @return $this
*/
public function execute(EventObserver $observer)
{
/** @var \Magento\Framework\Data\Tree\Node $menu */
$menu = $observer->getMenu();
$tree = $menu->getTree();
$data = [
'name' => __('Menu item label here'),
'id' => 'some-unique-id-here',
'url' => 'url goes here',
'is_active' => (expression to determine if menu item is selected or not)
];
$node = new Node($data, 'id', $tree, $menu);
$menu->addChild($node);
return $this;
}
}
Outras dicas
The simple way to do this is here given below. For example Here I am using Solwin/freego theme so I have to navigate
/httpdocs/app/design/frontend/Solwin/freego/Magento_Theme/templates/html/topmenu.phtml (it might be different in your case)
And here I can add as much as the menu I want with a Home link
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/**
* Top menu for store
*
* @see \Magento\Theme\Block\Html\Topmenu
*/
?>
<?php $columnsLimit = $block->getColumnsLimit() ? : 0; ?>
<?php $_menu = $block->getHtml('level-top', 'submenu', $columnsLimit) ?>
<?php
$helper = $this->helper( 'Solwin\Cpanel\Helper\Data' );
$baseUrl = $helper->getBaseUrl();
$curr_Url = $helper->getCurrentUrl();
$ishome = $helper->getIsHomePage();
$showhomelink = $helper->getEnablehomelink();
?>
<nav class="navigation" role="navigation">
<ul data-mage-init='{"menu":{"responsive":true, "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'>
<?php if ($showhomelink) { ?>
<li class="level0 level-top <?php if ($ishome) { ?> active <?php } ?>">
<a class="level-top" href="<?php echo $baseUrl; ?>">
Home
</a>
</li>
<?php } ?>
<li class="level0 level-top">
<a class="level-top" href="<?php echo $baseUrl; ?>about-us">
About us
</a>
</li>
<?php /* @escapeNotVerified */ echo $_menu; ?>
<li class="level0 level-top">
<a class="level-top" href="<?php echo $baseUrl; ?>faqs">
FAQs
</a>
</li>
<li class="level0 level-top">
<a class="level-top" href="<?php echo $baseUrl; ?>contact-us">
Contact Us
</a>
</li>
<li class="level0 level-top">
<a class="level-top" href="<?php echo $baseUrl; ?>account">
My Account
</a>
</li>
</ul>
</nav>
We can achieve this goal by overwrite default Magento file vendor/magento/module-theme/view/frontend/templates/html/topmenu.phtml. But this is not good practice by making changes in default Magento functionality. We will use the plugin to implement this.
Step -1 We have to create app/code/VendorName/ModuleName/etc/di.xml file where we will define our plugin.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- Add Plugin for add custom link in navigation -->
<type name="Magento\Theme\Block\Html\Topmenu">
<plugin name="add_menu_item_plugin" type="VendorName\ModuleName\Plugin\Topmenu" sortOrder="10" disabled="false"/>
</type>
</config>
Step -2 Now we have to create app/code/VendorName/ModuleName/Plugin/Topmenu.php
<?php
namespace Test\TestCustomMenu\Plugin;
class Topmenu
{
/**
* @param Context $context
* @param array $data
*/
public function __construct(
\Magento\Customer\Model\Session $session
) {
$this->Session = $session;
}
public function afterGetHtml(\Magento\Theme\Block\Html\Topmenu $topmenu, $html)
{
$swappartyUrl = $topmenu->getUrl('testCustomMenu/custommenu'); //here you can set link
$magentoCurrentUrl = $topmenu->getUrl('*/*/*', ['_current' => true, '_use_rewrite' => true]);
if (strpos($magentoCurrentUrl, 'testCustomMenu/custommenu') !== false) {
$html .= "
";
} else {
$html .= "
";
}
$html .= "" . __("Custom Menu") . "";
$html .= "
";
return $html;
}
}
Step -3 After adding above files please run following command :-
php bin/magento setup:di:compile
php bin/magento cache:flush
How can we move cms link at the beginning of the menu? Is it possible to add home link in front of all other links? On line 228, vendor/magento/module-theme/Block/Html/Topmenu.php
there is a method $child->setIsFirst($counter == 1);
, but it does not work.