Додавання посилання без категорії до навігаційних посилань у magento 2


29

Я не впевнений, що я тут роблю неправильно. Блок, який містить посилання на категорії, посилається на навігацію.секції. Я думав, що направляючи наступні аргументи до контейнера, я зможу створити під ним нове посилання. Будь-яка допомога вдячна.

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

Мені цікаво те саме .. Ви знайшли рішення для цього?

Обидва перераховані рішення працювали на мене.
тематик, який знавчан

Над якою версією Magento ви працюєте?
Разван Замфір

Відповіді:


34

[EDIT]
Мабуть, в останніх версіях M2 це вже не працює.
Дякую Максу за те, що вказав на це.
Для більш пізньої версії вам потрібно додати плагін Magento\Theme\Block\Html\Topmenuзамість спостерігача.
Додайте це доetc/frontend/di.xml

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

і створити файл класу плагінів [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]
Оригінальна відповідь:
Ви можете додати елементи до верхнього меню за допомогою події page_block_html_topmenu_gethtml_before.

Тож вам потрібно створити модуль з цими файлами (усі файли повинні бути app/code/[Namespace]/[Module]):

etc/module.xml - файл декларації модуля

<?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 - реєстраційний файл

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

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="[namespace]_[module]_observer" instance="[Namespace]\[Module]\Observer\Topmenu" />
    </event>
</config>

Observer/Topmenu.php - фактичний спостерігач

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

Тепер запустіть у cli, php bin/magento setup:upgradeщоб встановити модуль, і ви добре піти.


У Topmenu.php відсутня частина коду?
тематик, який знавчан

1
@Solide. Порядок посилань залежить від порядку виконання спостерігачів. Якщо спостерігач домашньої сторінки виконаний до каталогу першого, то спочатку слід додати посилання на домашню сторінку. Якщо ні, ви можете переглянути цей підхід для зміни порядку посилань: magento.stackexchange.com/q/7329/146 . підхід призначений для Magento1, але ви можете перевести його в код M2.
Маріус

1
@Marius: що має бути 'is_active'. Будь ласка, додайте приклад. я хочу активне посилання на цій сторінці.
zed Blackbeard

1
Для події використовується спостерігач. Плагін може працювати будь-яким загальнодоступним методом. Я б радив використовувати плагін-підхід, оскільки той використовується в ядрі, щоб додати категорії до верхнього меню.
Маріус

1
Вибачте, я відчуваю себе ідіотом, але як можна додати більше одного меню? Якщо я використовую $menu->addChild($node)не один раз, останній перевершує інші. Він показує лише одне меню (останнє).
pinicio

17

Чому всі завжди хочуть написати модуль. Я зробив це по-своєму, layout.xmlі це спрацювало як шарм:

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

як відкрити це посилання на новій вкладці?
jafar pinjar

Гарне питання. Знайдено щось у коді. Можливо, спробуйте це: <argument name = "attributes" xsi: type = "array"> <item name = "target" xsi: type = "string"> _ blank </item> </argument> Не перевірено, але є доступний варіант атрибутів.
Джонні Лонгнек

Створення модуля робить його набагато більш динамічним. Дуже багато клієнтів, з якими я працюю, хочуть робити самі речі, як у цьому випадку, створюючи сторінки та додаючи їх у топменю в певному порядку.
Рой Єуріссен

6

Ще одне рішення поза створенням модуля - це перезапис topmenu.phtml. Зауважу, що рішення, яке надає @Marius, - це найкращий спосіб зробити це, якщо ви маєте намір посилатись на спадкування класів навігації. Це відображається в мобільному меню Magento, лише без належного css. Ви можете використовувати аргумент css_class для відповідного стилю.

YourTheme / Magento_Theme / шаблони / 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>

Де я можу знайти приклад аргументу класу css?
camdixon


як ви посилаєте файл шаблону на XML-файл ..
Сарвеш Тіварі

6

Цю відповідь надає Маріус ♦ я щойно змінив її, щоб додати дочірню категорію в меню вкладки категорії, ви можете посилатися на відповідь Маріуса ♦. Я щойно змінив дочірній файл Topmenu.php, щоб додати дочірню категорію в основну категорію

<?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();
    }
}

Вам потрібно створити вузол для батьківської категорії та для дочірньої категорії, після чого ви можете призначити дочірню категорію батьківській категорії, використовуючи метод addChild, ось приклад

$contactsNode->addChild($warrantyRegistrationNode);

Спасибі! не зрозумів, що так просто додати підменю!
Джуліано Варгас

і сер, якщо я хочу показати свій спеціальний div на спеціальному посиланні, яке я додав Topmenu. Як коли я клацнув курсором миші на Посиланні, то він показує мій користувацький дів
Асад Хан

1

Використовуючи вищезазначену відповідь Маріуса, я додав пункти підменю. Я також показую спосіб редагування дерева перед створенням html, а потім як редагувати html безпосередньо після його створення. Працює в Magento 2.1. Оновіть Topmenu.php за допомогою цього:

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

1

Хочете додати посилання на верхню навігацію в межах <header>
Додавання посилання на сторінку CMS, Галерея

Тут редагуйте / розмістіть default.xml:

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

Додайте наступний код:

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

Це додає посилання на сторінку CMS, Галерея, з такими налаштуваннями:

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

Додайте таку стилізацію, щоб переконатися, що нове посилання правильно вирівнюється:

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

Результати коду (Продукти налаштовуються як категорія для прикладу)



0

Для тих, хто хоче додати is_activeвираз, особливо @zed Blackbeard, хто запитував вище.

Я використовував зв'язок контакту, і він також працюватиме із спеціальним модулем, оскільки я посилаюся на один.

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

// (вираз, щоб визначити, вибрано пункт меню чи ні)

Сподіваюся, це допоможе комусь.


0

Це також хороший варіант:

додаток / дизайн / 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>

-1

Що стосується посилання на навігаційне меню, кроків до цього не багато, я знайшов короткий посібник з цього процесу, він передбачає тему, яка перекриває topmenu.phtmlфайл з Magento_Themeмодуля: https://linkstraffic.net/adding-custom- menu-item-inside-magento2 / Я успішно протестував його, тому ділюсь ним із вами, хлопці.


Ласкаво просимо до Magento SE. Якщо ви публікуєте посилання у відповіді, будь ласка, переконайтесь, що відповідь все-таки є цінною, якщо посилання в певний час стане мертвою: Наприклад, підсумуйте пов’язану статтю або цитуйте відповідні частини. Це важливо, тому що StackExchange має на меті бути базою знань, а не форумом підтримки, який допомагає одній людині зараз. Майбутні відвідувачі все-таки повинні скористатися питаннями та відповідями.
Сіархей Учукхлебау
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.