33

I'm not sure what I'm doing wrong here. The block which holds the category links in is referenced to as navigation.sections. I thought by directing the following arguments toward the container I would be able to create a new link under it. Any help is appreciated.

<referenceContainer name="navigation.sections">
            <block class="Magento\Framework\View\Element\Html\Links" name="mylink">
                    <arguments>
                        <argument name="label" xsi:type="string">Mylink</argument>
                        <argument name="path" xsi:type="string">mypath</argument>
                        <argument name="css_class" xsi:type="string">mycss</argument>
                    </arguments>
            </block>
</referenceContainer>
Tirth Patel
  • 1,039
  • 8
  • 26
themanwhoknowstheman
  • 1,446
  • 3
  • 21
  • 37

12 Answers12

39

[EDIT]
Apparently, in latest versions of M2 this does not work anymore.
Thanks to Max for pointing this out.
For later version you need to add a plugin for Magento\Theme\Block\Html\Topmenu instead of an observer.
Add this to etc/frontend/di.xml

<type name="Magento\Theme\Block\Html\Topmenu">
    <plugin name="[module]-topmenu" type="[Namespace]\[Module]\Plugin\Block\Topmenu" />
</type>

and create the plugin class file [Namespace]/[Module]/Plugin/Block/Topmenu.php

<?php 

namespace [Namespace]\[Module]\Plugin\Block;

use Magento\Framework\Data\Tree\NodeFactory;

class Topmenu
{
    /**
     * @var NodeFactory
     */
    protected $nodeFactory;

    public function __construct(
        NodeFactory $nodeFactory
    ) {
        $this->nodeFactory = $nodeFactory;
    }

    public function beforeGetHtml(
        \Magento\Theme\Block\Html\Topmenu $subject,
        $outermostClass = '',
        $childrenWrapClass = '',
        $limit = 0
    ) {
        $node = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray(),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $subject->getMenu()->addChild($node);
    }

    protected function getNodeAsArray()
    {
        return [
            'name' => __('Label goes here'),
            'id' => 'some-unique-id-here',
            'url' => 'http://www.example.com/',
            'has_active' => false,
            'is_active' => false // (expression to determine if menu item is selected or not)
        ];
    }
}

[/EDIT]
Original answer:
You can add elements to the top menu using the event page_block_html_topmenu_gethtml_before.

So you need to create a module with these files (all the files should be in 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>

registration.php - the registration file

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '[Namespace]_[Module]',
    __DIR__
);

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>

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;
    }
}

Now run in the cli php bin/magento setup:upgrade to install the module and you are good to go.

Darren Felton
  • 1,307
  • 11
  • 18
Marius
  • 197,939
  • 53
  • 422
  • 830
  • Is Topmenu.php missing part of the code? – themanwhoknowstheman Jan 07 '16 at 16:42
  • @themanwhoknowstheman Sorry. It was a formatting issue. – Marius Jan 07 '16 at 17:11
  • What would be the proper way to add a css class to the link using this method? – themanwhoknowstheman Jan 08 '16 at 07:46
  • I don't think you can. but not sure. – Marius Jan 08 '16 at 07:53
  • Does this allow you to position the added link (for instance before all category links to show a home link in this menu)? – Solide Feb 25 '16 at 13:04
  • 1
    @Solide. The order of the links depend on the order the observers are executed. If your homepage observer is executed before the catalog one then the homepage link should be added first. If not, you can take a look at this approach for changing the order of the links: http://magento.stackexchange.com/q/7329/146. the approach is for Magento1, but you can translate it to M2 code. – Marius Feb 25 '16 at 13:29
  • Thank you Marius. For future reference, I was able to use the code from Marius to add a link to beginning of the category menu. The code is for Magento1 but the part where the category menu is rebuild does not need any editing to work with Magento2. – Solide Feb 25 '16 at 20:11
  • 1
    @Marius : what should be the 'is_active'. Please add some example. i want active link on this page. – Amit Maurya Mar 30 '16 at 10:37
  • Find a way to determine if the menu should be selected or not. It depends on the menu itself. – Marius Mar 30 '16 at 10:39
  • i have put url based expression but is not working and one more question can we set the position of custom menu ? – Amit Maurya Mar 30 '16 at 10:42
  • @Marius if i want to add sub-menu of this custom menu,

    And I want to add it in present menu how to add this?

    – ND17 Apr 27 '16 at 05:11
  • This solution seems to be broken as for Magento 2.0.9. – Max Oct 05 '16 at 10:41
  • @Max. It seams that you are right. I edited the answer with the way to do it for later versions. – Marius Oct 05 '16 at 11:01
  • Hi Marius, it seems that the Plugin/Topmenu.phpis missing some code, or am I wrong? $ php bin/magento setup:upgrade fails at this point. – Max Oct 06 '16 at 09:03
  • I don't think so. what fails? – Marius Oct 06 '16 at 09:17
  • I really like the Plugin approach ... but the code seems buggy to me

    $subject is not injected as Topmenu Object, but instead comes as an Interceptor Magento\Theme\Block\Html\Topmenu\Interceptor

    But more important, the function getMenu isn't available. Menu is a protected attribute in the Topmenu and there is no method provided to fetch it.

    – leedch Nov 02 '16 at 17:54
  • @leedch take another look I've revised the answer for slightly for you. FYI $subject is supposed to be passed in as an interceptor object. Magento generates this class in order for the Plugin to work and be able to observe the firing of the original class' public methods. This is the nature of plugins. Lastly the method you are looking for to fetch the protected $menu property is $subject->getMenu(). This comes from Topmenu, the Interceptor class extends Topmenu. – Darren Felton Dec 09 '16 at 16:42
  • On Magento 2.1.3 this module fails as well, it simply breaks the store. Could you check it? Worked so nicely months ago. – Max Jan 24 '17 at 08:24
  • Sorry but I don't have the strenght to check for every version. Check how the categories are added to the menu and do the same. – Marius Jan 24 '17 at 09:47
  • P-E-R-F-E-C-T!!! – Goldy Apr 06 '17 at 08:11
  • you can get example for adding child category – Vaibhav Ahalpara Jul 20 '17 at 05:52
  • Works like a charm, Thank You. One thing i'm confused about is what's the difference between observer Topmenu.php and plugin block Topmenu.phtml. Aren't they suppose to perform the same task? Do we suppose to use one of them? If yes, which one do you consider the preferred way? – Moax6629 Aug 01 '17 at 14:24
  • 1
    An observer is used on an event. A plugin can work on any public method. I would advice to use the plugin approach since that one is used in the core to add the categories to the top menu. – Marius Aug 01 '17 at 14:38
  • [Namespace] is [Vendor] and [Module] is [Modulename], right? – Razvan Zamfir Oct 26 '17 at 09:12
  • @RazvanZamfir right – Marius Oct 26 '17 at 09:44
  • 1
    Sorry, I feel like an idiot, but how can you add more than one menu? If I use $menu->addChild($node) more than once, the last one override the other ones. It only shows one menu (the last one). – pinicio Feb 23 '18 at 15:16
  • Notice this line 'id' => 'some-unique-id-here',. The value of the id must be unique. If you have 2 items with the same id the last one overrides the first one. – Marius Feb 23 '18 at 15:25
  • @pinicio You have to call $node->setIdField("id") besides making the id unique – Zsolti Jun 19 '18 at 16:11
  • Menu item created at first place. how to place new item to last.? – Alok Singh Sep 05 '18 at 03:49
  • @Marius Sir can you please explain me How can we create the dropdown on the link like on mouse hover I want to show my custom div on whenever I hover on the custom on the link – Asad Khan Apr 30 '19 at 14:48
  • Hello. How can I add Submenu for any top menu. I have used above code but it is adding as a top menu. – Arjun Aug 14 '20 at 06:59
20

Why does everybody always want to write a module. I did this in my layout.xml and it worked like a charm:

    <referenceBlock name="catalog.topnav">
        <block class="Magento\Framework\View\Element\Html\Link" name="contact-link">
            <arguments>
                <argument name="label" xsi:type="string" translate="true">Contact us</argument>
                <argument name="path" xsi:type="string" translate="true">contact</argument>
            </arguments>
        </block>
    </referenceBlock>
SR_Magento
  • 5,209
  • 13
  • 62
  • 103
Johnny Longneck
  • 431
  • 5
  • 13
8

This answer is provide by Marius♦ i have just modified it to add child category in category tab menu you can refer Marius♦'s answer. I just modified child Topmenu.php file to add child category in main category

<?php 

namespace Ktpl\Navigationlink\Plugin\Block;

use Magento\Framework\UrlInterface;
use Magento\Framework\Data\Tree\NodeFactory;
use Magento\Store\Model\StoreManagerInterface;

class Topmenu
{
    /**
     * @var NodeFactory
     */
    protected $nodeFactory;
    protected $urlBuilder;
    protected $_storeManager;

    public function __construct(
        UrlInterface $urlBuilder,
        NodeFactory $nodeFactory,
        StoreManagerInterface $storeManager
    ) {
        $this->urlBuilder = $urlBuilder;
        $this->nodeFactory = $nodeFactory;
        $this->_storeManager = $storeManager;
    }

    public function beforeGetHtml(
        \Magento\Theme\Block\Html\Topmenu $subject,
        $outermostClass = '',
        $childrenWrapClass = '',
        $limit = 0
    ) {
        // condition for store
        if($this->getStoreCode() == 'store_id'):
        $productNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Products','products'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $stockistsNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Stockists','stockists'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $ourstoryNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Our Story','ourstory'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $contactsNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Customer Care','contacts'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        /******* contacts's child *******/
        $warrantyRegistrationNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Warranty Registration','warranty-registration'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $faqNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Frequently Asked Questions','faq'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $ourProductGuaranteeNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Our Product Guarantee','our-product-guarantee'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $warrantiesNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Warranties, Repairs & Spare Parts','warranties-repairs-spare-parts'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $termsNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Terms & Conditions','terms-and-conditions'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $privacyPolicyNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Our Privacy Policy','privacy-policy'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $bookNode = $this->nodeFactory->create(
            [
                'data' => $this->getNodeAsArray('Book A Viewing','book-a-viewing'),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );

        $contactsNode->addChild($warrantyRegistrationNode);
        $contactsNode->addChild($faqNode);
        $contactsNode->addChild($ourProductGuaranteeNode);
        $contactsNode->addChild($warrantiesNode);
        $contactsNode->addChild($termsNode);
        $contactsNode->addChild($privacyPolicyNode);
        $contactsNode->addChild($bookNode);
        /******* end contacts's child *******/

        $subject->getMenu()->addChild($productNode);
        $subject->getMenu()->addChild($stockistsNode);
        $subject->getMenu()->addChild($ourstoryNode);
        $subject->getMenu()->addChild($contactsNode);
        endif;
    }

    protected function getNodeAsArray($name,$id)
    {
        return [
            'name' => __($name),
            'id' => $id,
            'url' => $this->urlBuilder->getUrl($id),
            'has_active' => false,
            'is_active' => false // (expression to determine if menu item is selected or not)
        ];
    }

    public function getStoreCode()
    {
        return $this->_storeManager->getStore()->getCode();
    }
}

You need to create node for parent category and for child category and after that you can assign child category to parent category by using addChild method here is an example

$contactsNode->addChild($warrantyRegistrationNode);
Vaibhav Ahalpara
  • 5,249
  • 4
  • 42
  • 81
7

Another solution outside of creating a module is overwriting topmenu.phtml. I will note that the solution provided by @Marius is the best way to do this if you intend for your links to inherit the navigation classes. This does show in Magento's mobile menu, just without the proper css. You could use the css_class argument to style accordingly.

YourTheme/Magento_Theme/templates/html/topmenu.phtml

<?php $columnsLimit = $block->getColumnsLimit() ?: 0; ?>
<?php $_menu = $block->getHtml('level-top', 'submenu', $columnsLimit) ?>

<nav class="navigation" role="navigation">
    <ul data-mage-init='{"menu":{"responsive":true, "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'>
        <?php /* @escapeNotVerified */ echo $_menu; ?>
        <?php echo $block->getChildHtml() ?>
    </ul>
</nav>

YourTheme/Magento_Theme/layout/default.xml

<referenceContainer name="catalog.topnav">
               <block class="Magento\Framework\View\Element\Html\Link\Current" name="your.link">
                    <arguments>
                        <argument name="label" xsi:type="string">Link-name</argument>
                        <argument name="path" xsi:type="string">Link-url</argument>
                    </arguments>
              </block>
</referenceContainer>
themanwhoknowstheman
  • 1,446
  • 3
  • 21
  • 37
3

Want to add a link to the top navigation within <header>
Adding a link to CMS page, Gallery

Edit/Place default.xml here:

app/design/frontend/Vendor/theme/Magento_Theme/layout/default.xml

Add the following code:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="catalog.topnav">
           <block class="Magento\Framework\View\Element\Html\Link\Current" name="gallery.link">
                <arguments>
                    <argument name="label" xsi:type="string">Gallery</argument>
                    <argument name="path" xsi:type="string">gallery</argument>
                </arguments>
          </block> 
       </referenceContainer>
    </body>
</page>

This adds a link to CMS page, Gallery, with the following settings:

Title = Gallery
Url Key = gallery
Link = https://example.com/gallery/

Add the following styling to ensure the new link aligns correctly:

.navigation .nav.item {
margin: 0 10px 0 0;
display: inline-block;
position: relative;
}

Results of the code (Products is setup as a category for an example)

Joshua34
  • 2,307
  • 1
  • 18
  • 25
3

You can get this by plugin after method

app/code/Vendor/Module/etc/di.xml

<type name="Magento\Theme\Block\Html\Topmenu">
    <plugin name="add_category_custom_item" type="Vendor\Module\Plugin\CategoryCustomItemPlugin" />
</type>

Now create app/code/Vendor/Module/Plugin/CategoryCustomItemPlugin.php

<?php

namespace Vendor\Module\Plugin;

class CategoryCustomItemPlugin
{

    public function afterGetHtml(\Magento\Theme\Block\Html\Topmenu $topmenu, $html)
    {
        $customurl= $topmenu->getUrl('yoururl'); //here you can set link
        $CurrentUrl = $topmenu->getUrl('*/*/*', ['_current' => true, '_use_rewrite' => true]);
        if (strpos($CurrentUrl,'yoururl') !== false) {
            $html .= "<li class=\"level0 nav-9 category-item level-top ui-menu-item active\">";
        } else {
            $html .= "<li class=\"level0 nav-9 category-item level-top ui-menu-item\">";
        }
        $html .= "<a href=\"" . $customurl. "\" class=\"level-top ui-corner-all\"><span class=\"ui-menu-icon ui-icon ui-icon-carat-1-e\"></span><span>" . __("yoururl") . "</span></a>";
        $html .= "</li>";
        return $html;
    }
}
Tirth Patel
  • 1,039
  • 8
  • 26
2

Using the above answer by Marius I added submenu items. I also show a way you can edit the tree before the html is created and then how to edit the html directly once it is created. It works in Magento 2.1 (EDIT: still working in 2.2.11). Update Topmenu.php with this:

<?php
namespace Seatup\Navigation\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Data\Tree\Node;
use Magento\Framework\Event\ObserverInterface;
class Topmenu implements ObserverInterface
{
    protected $_cmsBlock;

    public function __construct(
        \Magento\Cms\Block\Block $cmsBlock
    )
    {
        $this->_cmsBlock = $cmsBlock;
    }
    /**
     * @param EventObserver $observer
     * @return $this
     */
    public function execute(EventObserver $observer)
    {
        /** @var \Magento\Framework\Data\Tree\Node $menu */
        $eventName = $observer->getEvent()->getName();
        if($eventName == 'page_block_html_topmenu_gethtml_before'){
            // With the event name you can edit the tree here
            $menu = $observer->getMenu();
            $tree = $menu->getTree();
            $children = $menu->getChildren();

            foreach ($children as $child) {
                if($child->getChildren()->count() > 0){ //Only add menu items if it already has a dropdown (this could be removed)
                    $childTree = $child->getTree();
                    $data1 = [
                        'name'      => __('Menu item label here'),
                        'id'        => 'some-unique-id-here',
                        'url'       => 'url goes here',
                        'is_active' => FALSE
                    ];
                    $node1 = new Node($data1, 'id', $childTree, $child);
                    $childTree->addNode($node1, $child);
                }
            }
            return $this;
        } else if($eventName == 'page_block_html_topmenu_gethtml_after'){
            // With the event name you can edit the HTML output here
            $transport = $observer['transportObject'];

            //get the HTML
            $old_html = $transport->getHtml();

            //render the block. I am using a CMS block
            $new_output = $this->_cmsBlock->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('cms_block_identifier')->toHtml();
            //the transport now contains html for the group/class block
            //which doesn't matter, because we already extracted the HTML into a 
            //string primitive variable
            $new_html = str_replace('to find', $new_output , $old_html);    
            $transport->setHtml($new_html);
        }
    }
}
Cypher909
  • 308
  • 3
  • 9
1

If you want to add CMS Pages or other this would be best

https://github.com/Mestrona/Mestrona_CategoryRedirect

Worked for me :)

Jackson
  • 9,909
  • 29
  • 128
  • 217
1

Just for a navigation menu link, there is no much steps to achieve, I've found a short tutorial on doing that, it implies a theme which overrides the topmenu.phtml file from the Magento_Theme module : https://linkstraffic.net/adding-custom-menu-item-inside-magento2/ I've tested it successfully, so I share it with you guys.

Aman Alam
  • 1,318
  • 10
  • 25
Jimmy
  • 11
  • 1
  • Welcome to Magento SE. If you post links in an answer, please make sure that the answer is still valuable, if the link becomes dead at some time: For example, summarize the linked article or quote the relevant parts. This is important because StackExchange aims to be a knowledge database, not a support forum that helps one person right now. Future visitors should still benefit from the questions and answers. – Siarhey Uchukhlebau Jun 29 '17 at 22:29
1

For those looking to add is_active expression, especially @zed Blackbeard who asked above.

I've used to link the contact and it will work with custom module too as I am linking to one.

'is_active' => ($this->request->getFrontName() == 'contact' ? true : false)

// (expression to determine if menu item is selected or not)

Hope it helps anyone.

Rama Chandran M
  • 3,210
  • 13
  • 22
  • 38
Juliano Vargas
  • 2,521
  • 3
  • 25
  • 81
1

This is also a good option:

app/design/frontend/Vender/yourtheme/Magento_Theme/layout/default.xml

<referenceBlock name="header.links">
    <block class="Magento\Framework\View\Element\Html\Link" name="yourlinkname" before='wish-list-link'>
        <arguments>
            <argument name="label" xsi:type="string" translate="true">yourlink</argument>
            <argument name="path" xsi:type="string" translate="true">yourlink</argument>
        </arguments>
    </block>
</referenceBlock>
Sharfaraz Bheda
  • 1,323
  • 16
  • 28
0

Use below code to add menu and sub-menu / Child menu

Vendor/Module/etc/frontend/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="custom_productmenu_observer" instance="Vendor\Module\Observer\Topmenu" />
    </event>
</config>

Vendor/Module/Observer/Topmenu.php

<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Data\Tree\Node;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

class Topmenu implements ObserverInterface { protected $nodeFactory; protected $urlBuilder;

public function __construct(
    \Magento\Framework\Data\Tree\NodeFactory $nodeFactory,
    \Magento\Framework\UrlInterface $urlBuilder
) {
    $this-&gt;nodeFactory = $nodeFactory;
    $this-&gt;urlBuilder = $urlBuilder;
}

public function execute(EventObserver $observer) {
    $menu = $observer-&gt;getMenu();
    $menuNode = $this-&gt;nodeFactory-&gt;create(
        [
            'data' =&gt; $this-&gt;getNodeAsArrayzv(&quot;Menu Custom&quot;, &quot;custom-menu&quot;, &quot;/subtrate.html?sub=336&quot;),
            'idField' =&gt; 'id',
            'tree' =&gt; $menu-&gt;getTree(),
        ]
    );
    $menuNode-&gt;addChild(
        $this-&gt;nodeFactory-&gt;create(
            [
                'data' =&gt; $this-&gt;getNodeAsArrayzv(&quot;Custom Menu - Child Menu&quot;, &quot;child-menu&quot;, &quot;/subtrate.html?sub=336&quot;),
                'idField' =&gt; 'id',
                'tree' =&gt; $menu-&gt;getTree(),
            ]
        )
    );

    $menuNode-&gt;addChild(
        $this-&gt;nodeFactory-&gt;create(
            [
                'data' =&gt; $this-&gt;getNodeAsArrayzv(&quot;Custom Menu - Child Menu2&quot;, &quot;child-menu1&quot;, &quot;/subtrate.html?sub=356&quot;),
                'idField' =&gt; 'id1',
                'tree' =&gt; $menu-&gt;getTree(),
            ]
        )
    );
    $menu-&gt;addChild($menuNode);
    return $this;
}

protected function getNodeAsArrayzv($name, $id, $url) {
    return [
        'name' =&gt; __($name),
        'id' =&gt; $id,
        'url' =&gt; $url,
        'has_active' =&gt; false,
        'is_active' =&gt; false,
    ];
}

}

akashmalik
  • 486
  • 3
  • 10