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>

나도 똑같아 .. 해결책을 찾았 니?

나열된 두 가지 솔루션이 모두 효과가있었습니다.
themanwhoknowthetheman

어떤 마 젠토 버전을 작업 중입니까?
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)
        ];
    }
}

[/ EDIT]
원래 답변 :
event를 사용하여 최상위 메뉴에 요소를 추가 할 수 있습니다 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가 코드의 일부가 누락 되었습니까?
themanwhoknowthetheman

1
@ 솔리드. 링크의 순서는 관찰자가 실행되는 순서에 따라 다릅니다. 카탈로그 관찰자 전에 홈페이지 관찰자를 실행 한 경우 먼저 홈페이지 링크를 추가해야합니다. 그렇지 않은 경우 magento.stackexchange.com/q/7329/146 링크 순서를 변경하기위한이 접근 방식을 살펴볼 수 있습니다 . 이 접근 방식은 Magento1에 대한 것이지만 M2 코드로 변환 할 수 있습니다.
Marius

1
@Marius : 무엇이되어야 하는가 'is_active'. 몇 가지 예를 추가하십시오. 이 페이지에서 활성 링크를 원합니다.
zed Blackbeard 10

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

좋은 질문. 코드에서 무언가를 발견했습니다. <argument name = "attributes"xsi : type = "array"> <item name = "target"xsi : type = "string"> _ blank </ item> </ argument> 테스트되지 않았지만 속성 옵션을 사용할 수 있습니다.
Johnny Longneck

모듈을 만들면 훨씬 더 역동적입니다. 내가 함께 일하는 많은 고객들은이 경우와 같이 페이지를 작성하고 특정 순서로 최상위 메뉴에 추가하려고합니다.
Roy Jeurissen

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 클래스 인수의 예를 어디에서 찾을 수 있습니까?
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);

감사! 하위 메뉴를 쉽게 추가 할 수 있다는 것을 몰랐습니다!
Juliano Vargas

그리고 선생님 나는 내 사용자 지정 표시 할 경우 DIV 링크 내가 추가 지정에를 Topmenu. 링크에 마우스를 올리면 내 사용자 지정 div가 표시됩니다
Asad Khan

1

Marius의 위 답변을 사용하여 하위 메뉴 항목을 추가했습니다. 또한 HTML을 만들기 전에 트리를 편집 할 수있는 방법과 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 : 거짓)

// (메뉴 항목 선택 여부를 결정하는 표현)

그것이 누군가를 돕기를 바랍니다.


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는 현재 한 사람을 돕는 지원 포럼이 아닌 지식 데이터베이스가되기 때문에 중요합니다. 미래의 방문객들은 여전히 ​​질문과 답변의 혜택을 받아야합니다.
Siarhey Uchukhlebau
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.