Thêm một liên kết không thể loại vào các liên kết điều hướng trong magento 2


29

Tôi không chắc mình đang làm gì sai ở đây. Khối chứa các liên kết thể loại trong được tham chiếu đến như điều hướng. Tôi nghĩ bằng cách hướng các đối số sau vào container, tôi sẽ có thể tạo một liên kết mới bên dưới nó. Bất kỳ trợ giúp được đánh giá cao.

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

Tôi đang tự hỏi tương tự .. Bạn đã tìm thấy một giải pháp cho nó?

Cả hai giải pháp được liệt kê đã làm việc cho tôi.
themanwhoknowstheman

Phiên bản Magento nào bạn đang làm việc?
Razvan Zamfir

Câu trả lời:


34

[EDIT]
Rõ ràng, trong các phiên bản mới nhất của M2, điều này không còn hoạt động nữa.
Cảm ơn Max đã chỉ ra điều này.
Đối với phiên bản mới hơn, bạn cần thêm một plugin Magento\Theme\Block\Html\Topmenuthay vì một người quan sát.
Thêm cái này vàoetc/frontend/di.xml

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

và tạo tập tin lớp 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]
Câu trả lời gốc:
Bạn có thể thêm các yếu tố vào menu trên cùng bằng sự kiện page_block_html_topmenu_gethtml_before.

Vì vậy, bạn cần tạo một mô-đun với các tệp này (tất cả các tệp phải nằm trong app/code/[Namespace]/[Module]):

etc/module.xml - tệp khai báo mô-đun

<?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 - hồ sơ đăng ký

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

etc/frontend/events.xml - tệp khai báo sự kiện

<?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 - người quan sát thực tế

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

Bây giờ chạy trong cli php bin/magento setup:upgradeđể cài đặt mô-đun và bạn tốt để đi.


Là Topmenu.php thiếu một phần của mã?
themanwhoknowstheman

1
@Solide. Thứ tự của các liên kết phụ thuộc vào thứ tự các quan sát viên được thực thi. Nếu người quan sát trang chủ của bạn được thực thi trước danh mục thì liên kết trang chủ sẽ được thêm vào trước. Nếu không, bạn có thể xem phương pháp này để thay đổi thứ tự của các liên kết: magento.stackexchange.com/q/7329/146 . Cách tiếp cận dành cho Magento1, nhưng bạn có thể dịch nó sang mã M2.
Marius

1
@Marius: những gì nên là 'is_active'. Vui lòng thêm một số ví dụ. tôi muốn liên kết hoạt động trên trang này.
zed Blackbeard

1
Một người quan sát được sử dụng trên một sự kiện. Một plugin có thể hoạt động trên bất kỳ phương pháp nào. Tôi sẽ khuyên bạn nên sử dụng cách tiếp cận plugin vì nó được sử dụng trong lõi để thêm các danh mục vào menu trên cùng.
Marius

1
Xin lỗi, tôi cảm thấy như một thằng ngốc, nhưng làm thế nào bạn có thể thêm nhiều hơn một menu? Nếu tôi sử dụng $menu->addChild($node)nhiều lần, cái cuối cùng sẽ ghi đè lên những cái khác. Nó chỉ hiển thị một menu (cái cuối cùng).
pinnes

17

Tại sao mọi người luôn muốn viết một mô-đun. Tôi đã làm điều này trong tôi layout.xmlvà nó hoạt động như một cơ duyên:

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

Làm thế nào để mở liên kết đó trong tab mới?
jafar pinjar

Câu hỏi hay. Tìm thấy một cái gì đó trong mã. Có thể thử điều này: <argument name = "thuộc tính" xsi: type = "mảng"> <item name = "target" xsi: type = "string"> _ blank </ item> </ argument> Không được kiểm tra, nhưng có tùy chọn thuộc tính có sẵn.
Johnny Longneck

Tạo một mô-đun làm cho nó năng động hơn nhiều. Rất nhiều khách hàng tôi làm việc muốn tự làm mọi thứ như trong trường hợp này tạo các trang và thêm chúng vào topmenu theo một thứ tự cụ thể.
Roy Jeurissen

6

Một giải pháp khác ngoài việc tạo ra một mô-đun là ghi đè topmenu.phtml. Tôi sẽ lưu ý rằng giải pháp được cung cấp bởi @Marius là cách tốt nhất để làm điều này nếu bạn có ý định cho các liên kết của mình kế thừa các lớp điều hướng. Điều này không hiển thị trong menu di động của Magento, chỉ cần không có css thích hợp. Bạn có thể sử dụng đối số css_group để tạo kiểu cho phù hợp.

YourTheme / Magento_Theme / samples / 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>

Tôi có thể tìm thấy một ví dụ về đối số lớp css ở đâu?
camdixon


Làm thế nào để bạn liên kết tệp mẫu với tệp xml ..
Sarvesh Tiwari

6

Câu trả lời này được cung cấp bởi Marius ♦ tôi vừa sửa đổi nó để thêm danh mục con trong menu tab danh mục bạn có thể tham khảo câu trả lời của Marius ♦. Tôi vừa sửa đổi tập tin Topmenu.php con để thêm danh mục con trong danh mục chính

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

Bạn cần tạo nút cho danh mục cha mẹ và cho danh mục con và sau đó bạn có thể gán danh mục con cho danh mục cha mẹ bằng cách sử dụng phương thức addChild ở đây là một ví dụ

$contactsNode->addChild($warrantyRegistrationNode);

Cảm ơn! không nhận ra rằng thật dễ dàng để thêm Submenu!
Juliano Vargas

và thưa ông nếu tôi muốn hiển thị div tùy chỉnh của mình trên Liên kết tùy chỉnh mà tôi đã thêm vào Topmenu. Giống như khi tôi di chuột vào Liên kết thì nó hiển thị div
Asad Khan

1

Sử dụng câu trả lời trên của Marius tôi đã thêm các mục menu con. Tôi cũng chỉ ra một cách bạn có thể chỉnh sửa cây trước khi html được tạo và sau đó là cách chỉnh sửa html trực tiếp sau khi được tạo. Nó hoạt động trong Magento 2.1. Cập nhật Topmenu.php với điều này:

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

Muốn thêm một liên kết đến điều hướng hàng đầu trong <header>
Thêm một liên kết đến trang CMS, Thư viện

Chỉnh sửa / Đặt default.xml tại đây:

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

Thêm mã sau đây:

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

Điều này thêm một liên kết đến trang CMS, Thư viện, với các cài đặt sau:

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

Thêm kiểu dáng sau để đảm bảo liên kết mới căn chỉnh chính xác:

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

Kết quả của mã (Sản phẩm được thiết lập làm danh mục cho một ví dụ)



0

Đối với những người tìm kiếm để thêm is_active biểu thức, đặc biệt là @ned Blackbeard, người đã hỏi ở trên.

Tôi đã từng liên kết với liên hệ và nó cũng sẽ hoạt động với mô-đun tùy chỉnh khi tôi đang liên kết với một liên hệ.

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

// (biểu thức để xác định xem mục menu có được chọn hay không)

Hy vọng nó sẽ giúp được bất cứ ai.


0

Đây cũng là một lựa chọn tốt:

ứng dụng / thiết kế / 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

Chỉ cần một liên kết menu điều hướng, không có nhiều bước để đạt được, tôi đã tìm thấy một hướng dẫn ngắn để làm điều đó, nó ngụ ý một chủ đề ghi đè lên topmenu.phtmltệp từ Magento_Thememô-đun: https://linkstraffic.net/adding-custom- menu-item-Inside-magento2 / Tôi đã thử nghiệm thành công, vì vậy tôi chia sẻ nó với các bạn.


Chào mừng đến với Magento SE. Nếu bạn đăng liên kết trong một câu trả lời, vui lòng đảm bảo rằng câu trả lời vẫn còn giá trị, nếu liên kết bị chết vào một lúc nào đó: Ví dụ: tóm tắt bài viết được liên kết hoặc trích dẫn các phần có liên quan. Điều này rất quan trọng vì StackExchange nhằm mục đích trở thành một cơ sở dữ liệu tri thức, không phải là một diễn đàn hỗ trợ giúp một người ngay bây giờ. Khách truy cập trong tương lai vẫn nên được hưởng lợi từ các câu hỏi và câu trả lời.
Siarhey Uchukhlebau
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.