การเพิ่มลิงก์ที่ไม่ใช่หมวดหมู่ให้กับลิงก์การนำทางใน 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>

ฉันสงสัยเหมือนกัน .. คุณพบวิธีแก้ปัญหาหรือไม่

โซลูชันทั้งสองที่แสดงรายการอยู่ได้ผลสำหรับฉัน
themanwhoknowstheman

คุณกำลังทำอะไรในเวอร์ชัน Magento?
Razvan Zamfir

คำตอบ:


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 ได้
Marius

1
@Marius: 'is_active'สิ่งที่ควรจะเป็น โปรดเพิ่มตัวอย่าง ฉันต้องการลิงค์ที่ใช้งานในหน้านี้
zed Blackbeard

1
ผู้สังเกตการณ์จะใช้กับเหตุการณ์ ปลั๊กอินสามารถทำงานกับวิธีการสาธารณะใด ๆ ฉันอยากจะแนะนำให้ใช้วิธีการเสริมเนื่องจากมันถูกใช้ในแกนกลางเพื่อเพิ่มหมวดหมู่ลงในเมนูด้านบน
Marius

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

คำถามที่ดี. พบบางสิ่งในรหัส อาจลองวิธีนี้: <อาร์กิวเมนต์ name = "attribute" xsi: type = "array"> <item name = "target" xsi: type = "string"> _ blank </item> </argem> </argem> ไม่ได้ทดสอบ แต่มี ตัวเลือกคุณลักษณะที่มีอยู่
Johnny Longneck

การสร้างโมดูลทำให้มีชีวิตชีวามากขึ้น ลูกค้าจำนวนมากที่ฉันทำงานด้วยต้องการทำสิ่งที่ตนเองชอบในกรณีนี้การสร้างหน้าและเพิ่มพวกเขาไปยัง topmenu ตามลำดับที่เฉพาะเจาะจง
Roy Jeurissen

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 / รูปแบบ / 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 ได้อย่างไร ..
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);

ขอบคุณ! ไม่ทราบว่ามันเป็นเรื่องง่ายที่จะเพิ่ม Submenu!
Juliano Vargas

และเซอร์ถ้าผมต้องการที่จะแสดงของฉันเองdivTopmenuกำหนดเองการเชื่อมโยงฉันเพิ่มใน เหมือนตอนที่ฉันเลื่อนเมาส์ไปที่ลิงค์มันจะแสดง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 () == 'ติดต่อ'? จริง: เท็จ)

// (นิพจน์เพื่อพิจารณาว่าได้เลือกรายการเมนูหรือไม่)

หวังว่ามันจะช่วยให้ทุกคน


0

นี่เป็นตัวเลือกที่ดี:

app / ออกแบบ / ส่วนหน้า / Vender / yourtheme / Magento_Theme / รูปแบบ / 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 มีเป้าหมายที่จะเป็นฐานข้อมูลความรู้ไม่ใช่ฟอรัมสนับสนุนที่ช่วยคนคนหนึ่งในขณะนี้ ผู้เยี่ยมชมในอนาคตควรได้รับประโยชน์จากคำถามและคำตอบ
Siarhey Uchukhlebau
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.