2

So I've already hooked the "page_block_html_topmenu_gethtml_before" event with the observer class, I can add items to the menu tree, and it works fine, but I can't prepend items to the menu tree object. here is my code:

events.xml:

<?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="topmenu_load_pre" instance="<VENDOR>\<MODULE>\Observer\TopmenuLoadPre" />
    </event>
</config>

TopmenuLoadPre.php:

<?php

namespace <VENDOR>\<MODULE>\Observer;

class TopmenuLoadPre implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Framework\UrlInterface
     */
    private $_urlInterface;
    /**
     * @var \Magento\Framework\App\Request\Http
     */
    private $_request;

    /**
     * TopmenuLoadPre constructor.
     * @param \Magento\Framework\UrlInterface $urlInterface
     * @param \Magento\Framework\App\Request\Http $request
     */
    public function __construct(
        \Magento\Framework\UrlInterface $urlInterface,
        \Magento\Framework\App\Request\Http $request
    )
    {
        $this->_urlInterface = $urlInterface;
        $this->_request = $request;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Framework\Data\Tree\Node $menu */
        $menu = $observer->getData('menu');

        // we don't have the option to prepend menu item, so...
        // TODO: clone menu tree

        // remove all menu items
        foreach ($menu->getChildren() as $node) {
            $menu->removeChild($node);
        }

        // add item that I want to be first
        $this->addItem($menu, 'First One', 'very-left-one');

        // TODO: add the system default menu items here.

    }

    /**
     * @param \Magento\Framework\Data\Tree\Node $parentNode
     * @param string $name
     * @param string $slug
     * @return \Magento\Framework\Data\Tree\Node
     */
    private function addItem($parentNode, $name, $slug) {
        $data = [
            'name' => __($name),
            'url' => $this->_urlInterface->getUrl($slug),
            'id' => 'uid-' . $slug,
            'is_active' => ( $this->_request->getFrontName() == $slug ),
        ];
        $newNode = new \Magento\Framework\Data\Tree\Node($data, 'id', $parentNode->getTree());
        $parentNode->addChild($newNode);
        return $newNode;
    }

}

The only reason I'm not getting rid of the default menu is that it already has mobile menu support and automatically adds these items in the mobile sections-navigation.

Any help is greatly appreciated. Thanks.

Your Answer

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

Browse other questions tagged or ask your own question.