Menambahkan tautan non-kategori ke tautan navigasi di magento 2


29

Saya tidak yakin apa yang saya lakukan salah di sini. Blok yang menampung tautan kategori dirujuk sebagai navigasi.bagian. Saya pikir dengan mengarahkan argumen berikut ke wadah saya akan dapat membuat tautan baru di bawahnya. Bantuan apa pun dihargai.

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

Saya bertanya-tanya sama .. Apakah Anda menemukan solusi untuk itu?

Kedua solusi yang tercantum telah bekerja untuk saya.
themanwhoknowstheman

Versi Magento apa yang sedang Anda kerjakan?
Razvan Zamfir

Jawaban:


34

[EDIT]
Rupanya, dalam versi terbaru M2 ini tidak berfungsi lagi.
Terima kasih kepada Max karena telah menunjukkan ini.
Untuk versi yang lebih baru, Anda perlu menambahkan plugin untuk Magento\Theme\Block\Html\Topmenubukan pengamat.
Tambahkan ini keetc/frontend/di.xml

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

dan buat file kelas plugin [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]
Jawaban asli:
Anda dapat menambahkan elemen ke menu atas menggunakan acara page_block_html_topmenu_gethtml_before.

Jadi, Anda perlu membuat modul dengan file-file ini (semua file harus dalam app/code/[Namespace]/[Module]):

etc/module.xml - file deklarasi modul

<?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 - file pendaftaran

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

etc/frontend/events.xml - file pernyataan acara

<?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 - pengamat yang sebenarnya

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

Sekarang jalankan di cli php bin/magento setup:upgradeuntuk menginstal modul dan Anda baik untuk pergi.


Apakah Topmenu.php tidak ada bagian dari kode?
themanwhoknowstheman

1
@Solide. Urutan tautan tergantung pada urutan pengamat dieksekusi. Jika pengamat beranda Anda dieksekusi sebelum katalog satu maka tautan beranda harus ditambahkan terlebih dahulu. Jika tidak, Anda dapat melihat pendekatan ini untuk mengubah urutan tautan: magento.stackexchange.com/q/7329/146 . pendekatannya adalah untuk Magento1, tetapi Anda bisa menerjemahkannya ke kode M2.
Marius

1
@Marius: apa yang seharusnya 'is_active'. Silakan tambahkan beberapa contoh. saya ingin tautan aktif di halaman ini.
zed Blackbeard

1
Seorang pengamat digunakan pada suatu acara. Plugin dapat bekerja pada metode publik apa pun. Saya akan menyarankan untuk menggunakan pendekatan plugin karena yang digunakan dalam inti untuk menambahkan kategori ke menu paling atas.
Marius

1
Maaf, saya merasa seperti orang idiot, tetapi bagaimana Anda bisa menambahkan lebih dari satu menu? Jika saya menggunakan $menu->addChild($node)lebih dari sekali, yang terakhir menimpa yang lain. Ini hanya menampilkan satu menu (yang terakhir).
pinicio

17

Mengapa semua orang selalu ingin menulis modul. Saya melakukan ini di saya layout.xmldan itu bekerja seperti pesona:

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

cara membuka tautan itu di tab baru?
jafar pinjar

Pertanyaan bagus. Menemukan sesuatu dalam kode. Mungkin coba ini: <argumen name = "atribut" xsi: type = "array"> <item name = "target" xsi: type = "string"> _ blank </item> </argument> Tidak diuji, tetapi ada opsi atribut tersedia.
Johnny Longneck

Membuat modul membuatnya lebih dinamis. Banyak pelanggan saya bekerja dengan ingin melakukan hal-hal sendiri seperti dalam hal ini membuat halaman dan menambahkannya ke topmenu dalam urutan tertentu.
Roy Jeurissen

6

Solusi lain di luar membuat modul adalah menimpa topmenu.phtml. Saya akan mencatat bahwa solusi yang disediakan oleh @Marius adalah cara terbaik untuk melakukan ini jika Anda bermaksud untuk tautan Anda untuk mewarisi kelas navigasi. Ini ditampilkan di menu seluler Magento, hanya tanpa css yang tepat. Anda bisa menggunakan argumen css_class untuk memberi gaya yang sesuai.

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>

Di mana saya dapat menemukan contoh argumen kelas css?
camdixon


bagaimana Anda menautkan file template ke file xml ..
Sarvesh Tiwari

6

Jawaban ini disediakan oleh Marius ♦ Saya baru saja mengubahnya untuk menambahkan kategori anak di menu tab kategori Anda dapat merujuk jawaban Marius ♦. Saya baru saja memodifikasi file Topmenu.php anak untuk menambahkan kategori anak di kategori utama

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

Anda perlu membuat simpul untuk kategori induk dan untuk kategori anak dan setelah itu Anda dapat menetapkan kategori anak ke kategori induk dengan menggunakan metode addChild di sini adalah contoh

$contactsNode->addChild($warrantyRegistrationNode);

Terima kasih! tidak menyadari itu mudah untuk menambahkan Submenu!
Juliano Vargas

dan Pak jika saya ingin menampilkan div kustom saya pada Link kustom yang saya tambahkan Topmenu. Seperti ketika saya mengarahkan mouse pada Link maka itu menunjukkan div
Asad Khan

1

Menggunakan jawaban di atas oleh Marius saya menambahkan item submenu. Saya juga menunjukkan cara Anda dapat mengedit pohon sebelum html dibuat dan kemudian bagaimana mengedit html langsung setelah itu dibuat. Ini bekerja di Magento 2.1. Perbarui Topmenu.php dengan ini:

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

Ingin menambahkan tautan ke navigasi teratas di dalam <header>
Menambahkan tautan ke halaman CMS, Galeri

Edit / Tempatkan default.xml di sini:

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

Tambahkan kode berikut:

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

Ini menambahkan tautan ke halaman CMS, Galeri, dengan pengaturan berikut:

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

Tambahkan gaya berikut untuk memastikan tautan baru sejajar dengan benar:

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

Hasil kode (Produk diatur sebagai kategori sebagai contoh)



0

Bagi mereka yang ingin menambahkan is_active ekspresi, terutama @bb Blackbeard yang bertanya di atas.

Saya sudah terbiasa menautkan kontak dan itu akan berfungsi dengan modul khusus juga karena saya menautkan ke satu.

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

// (ekspresi untuk menentukan apakah item menu dipilih atau tidak)

Semoga ini bisa membantu siapa saja.


0

Ini juga merupakan pilihan yang baik:

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

Hanya untuk tautan menu navigasi, tidak ada banyak langkah untuk dicapai, saya telah menemukan tutorial singkat tentang melakukan itu, itu menyiratkan tema yang menimpa topmenu.phtmlfile dari Magento_Thememodul: https://linkstraffic.net/adding-custom- menu-item-inside-magento2 / Saya sudah mengujinya dengan sukses, jadi saya bagikan dengan kalian.


Selamat datang di Magento SE. Jika Anda memposting tautan dalam suatu jawaban, harap pastikan bahwa jawabannya masih berharga, jika tautan tersebut mati pada suatu waktu: Misalnya, rangkum artikel yang ditautkan atau kutip bagian yang relevan. Ini penting karena StackExchange bertujuan untuk menjadi basis data pengetahuan, bukan forum dukungan yang membantu satu orang saat ini. Pengunjung masa depan harus tetap mendapat manfaat dari pertanyaan dan jawaban.
Siarhey Uchukhlebau
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.