Like in Magento1, the Topmenu html structure is still pretty hardcoded.
To change the html markup of the submenus in 2.0, I added a plugin which altered the getHtml
Method of Magento\Theme\Block\Html\Topmenu
This was already pretty hacky since I extended my Plugin from the Topmenu and then called the _getHtml
Method from my instance instead of the original Topmenu instance and did not call the $proceed
callback function.
Despite not calling $proceed
beeing really rude, the only alternative I had in mind was setting a preference and overriding the _getSubMenu
method. Here is the original plugin class:
<?php
namespace Bragento2\Base\Model\Theme\Html\Topmenu;
use Magento\Framework\DataObject;
use Magento\Theme\Block\Html\Topmenu;
class Plugin extends Topmenu
{
public function aroundGetHtml(
Topmenu $subject,
$proceed,
$outermostClass = '',
$childrenWrapClass = '',
$limit = 0
) {
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_before',
['menu' => $this->_menu, 'block' => $this]
);
$this->_menu->setOutermostClass($outermostClass);
$this->_menu->setChildrenWrapClass($childrenWrapClass);
$html = $this->_getHtml($this->_menu, $childrenWrapClass, $limit);
$transportObject = new DataObject(['html' => $html]);
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_after',
['menu' => $this->_menu, 'transportObject' => $transportObject]
);
$html = $transportObject->getHtml();
return $html;
}
/**
* 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 = null;
if ($childLevel == 0 && $limit) {
$colStops = $this->_columnBrake($child->getChildren(), $limit);
}
$html .= '<div class="nav__flyout level' . $childLevel . '"><ul class="container">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul></div>';
return $html;
}
}
Now to the real Problem:
In Magento 2.1, the category Items are not anymore added by an Observer, but a plugin on the getHtml Method. Since I also have a Plugin which does not call the $proceed method, the category items are not added anymore (So this won't work anymore and I need an alternative)
Next thing I tried was changing the preference to my own Topmenu block class. But since the plugin, that adds the category items is defined for the original Topmenu class, this also does not work.
To my question: How can I change the html markup of the topmenu's submenus in Magento 2.1?
Best Answer
You should use Observer
etc/frontend/events.xml
Observer/Html/Topmenu.php
And you will can render this.
Also You can Define Layout
And Call Custom Block
And replace with html in transport