magento 2のナビゲーションリンクにカテゴリ以外のリンクを追加する


29

ここで何が間違っているのかわかりません。カテゴリリンクを保持するブロックは、navigation.sectionsとして参照されます。次の引数をコンテナに向けることで、その下に新しいリンクを作成できると考えました。どんな助けも大歓迎です。

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

私は同じことを疑問に思っています。あなたはそれに対する解決策を見つけましたか?

リストされている両方のソリューションは私のために働いています。
-themanwhothetheman

作業しているMagentoのバージョンは何ですか?
ラズバンザンフィル

回答:


34

[編集]
どうやら、M2の最新バージョンでは、これはもう機能しません。
これを指摘してくれたMaxに感謝します。
それ以降のバージョン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)
        ];
    }
}

[/編集]
元の回答:
イベントを使用して、トップメニューに要素を追加できます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にコードの一部が欠けていますか?
themanwhoknowstheman

1
@Solide。リンクの順序は、オブザーバーが実行される順序に依存します。ホームページオブザーバーがカタログの前に実行される場合、ホームページリンクが最初に追加される必要があります。そうでない場合は、リンクの順序を変更するためのこの方法をご覧ください:magento.stackexchange.com/q/7329/146 このアプローチはMagento1向けですが、M2コードに変換できます。
マリウス

1
@Marius:どうあるべきか'is_active'。例をいくつか追加してください。このページにアクティブリンクが必要です。
ZED黒ひげ

1
オブザーバーはイベントで使用されます。プラグインは、任意のパブリックメソッドで機能します。プラグインアプローチはトップメニューにカテゴリを追加するためにコアで使用されるため、プラグインアプローチを使用することをお勧めします。
マリウス

1
申し訳ありませんが、私は馬鹿のように感じますが、どうして複数のメニューを追加できますか?$menu->addChild($node)複数回使用すると、最後のものが他のものを上書きします。1つのメニュー(最後のメニュー)のみを表示します。
ピニシオ

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>

そのリンクを新しいタブで開く方法は?
ジャファーピンジャー

良い質問。コードに何かが見つかりました。おそらくこれを試してください:<argument name = "attributes" xsi:type = "array"> <item name = "target" xsi:type = "string"> _ blank </ item> </ argument>テストされていませんが、利用可能な属性オプション。
ジョニーロングネック

モジュールを作成すると、はるかに動的になります。私が仕事をしている多くの顧客は、この場合はページを作成し、特定の順序でトップメニューに追加するようなものを自分でやりたいと思っています。
ロイジュリセン

6

モジュールの作成以外の別のソリューションは、topmenu.phtmlを上書きすることです。リンクがナビゲーションクラスを継承する場合、@ Mariusが提供するソリューションがこれを行う最適な方法であることに注意してください。これは、適切なCSSなしで、Magentoのモバイルメニューに表示されます。それに応じてスタイル設定するには、css_class引数を使用できます。

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>

cssクラス引数の例はどこにありますか?
カムディクソン


テンプレートファイルをxmlファイルにリンクする方法..
Sarvesh Tiwari

6

この回答はMarius♦によって提供されています。Marius♦の回答を参照できるカテゴリタブメニューに子カテゴリを追加するように変更しました。子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。リンク上にマウスを置いたときのように、カスタムdivが
Asad Khan

1

Mariusによる上記の回答を使用して、サブメニュー項目を追加しました。また、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

これも良いオプションです:

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>

-1

ナビゲーションメニューリンクについては、達成する手順はあまりありません。そのための短いチュートリアルを見つけました。モジュールのtopmenu.phtmlファイルをオーバーライドするテーマを示していますMagento_Theme https //linkstraffic.net/adding-custom- menu-item-inside-magento2 / テストに成功したので、皆さんと共有します。


Magento SEへようこそ。回答にリンクを投稿する場合、リンクがいつか無効になった場合、回答がまだ価値があることを確認してください。たとえば、リンクされた記事を要約したり、関連する部分を引用したりします。StackExchangeは、現在1人のユーザーを支援するサポートフォーラムではなくナレッジデータベースを目指しているため、これは重要です。将来の訪問者は引き続き質問と回答の恩恵を受けるはずです。
Siarhey Uchukhlebau
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.