I am wondering how to add programmatically a new link (to main top menu in header) with submenu (custom content visible on hover - styles is not a problem).
How to achieve that, via xml or via (php) plugin?
More descriptive image below:
I am wondering how to add programmatically a new link (to main top menu in header) with submenu (custom content visible on hover - styles is not a problem).
How to achieve that, via xml or via (php) plugin?
More descriptive image below:
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;
}
}
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
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>
you can get from this code.
getColumnsLimit() ? : 0; ?> getHtml('level-top', 'submenu', $columnsLimit) ?>then not got then you can check it via xml code. or not done then goto block and add topmenu.phtml path.
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.