Aggiunta di un collegamento non di categoria ai collegamenti di navigazione in magento 2


29

Non sono sicuro di cosa sto facendo di sbagliato qui. Il blocco che contiene i collegamenti di categoria viene indicato come navigation.sections. Ho pensato indirizzando i seguenti argomenti verso il contenitore sarei stato in grado di creare un nuovo link sotto di esso. Qualsiasi aiuto è apprezzato.

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

Mi chiedo lo stesso .. Hai trovato una soluzione per questo?

Entrambe le soluzioni elencate hanno funzionato per me.
themanwhokststman

Su quale versione di Magento stai lavorando?
Razvan Zamfir,

Risposte:


34

[EDIT]
Apparentemente, nelle ultime versioni di M2 questo non funziona più.
Grazie a Max per averlo segnalato.
Per la versione successiva è necessario aggiungere un plug-in Magento\Theme\Block\Html\Topmenuanziché un osservatore.
Aggiungi questo aetc/frontend/di.xml

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

e crea il file di classe del 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]
Risposta originale:
puoi aggiungere elementi al menu principale usando l'evento page_block_html_topmenu_gethtml_before.

Quindi è necessario creare un modulo con questi file (tutti i file dovrebbero essere in app/code/[Namespace]/[Module]):

etc/module.xml - il file di dichiarazione del modulo

<?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 - il file di registrazione

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

etc/frontend/events.xml - il file di dichiarazione degli eventi

<?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 - l'osservatore reale

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

Ora esegui il cli php bin/magento setup:upgradeper installare il modulo e sei a posto.


Topmenu.php manca parte del codice?
temono che l'uomo lo sappia il

1
@Solide. L'ordine dei collegamenti dipende dall'ordine in cui vengono eseguiti gli osservatori. Se l'osservatore della home page viene eseguito prima di quello del catalogo, è necessario aggiungere prima il collegamento alla home page. In caso contrario, puoi dare un'occhiata a questo approccio per modificare l'ordine dei collegamenti: magento.stackexchange.com/q/7329/146 . l'approccio è per Magento1, ma è possibile tradurlo in codice M2.
Marius

1
@Marius: quale dovrebbe essere il 'is_active'. Per favore, aggiungi qualche esempio. Voglio un link attivo su questa pagina.
zed Barbanera,

1
Un osservatore viene utilizzato su un evento. Un plugin può funzionare su qualsiasi metodo pubblico. Consiglierei di utilizzare l'approccio plug-in in quanto quello utilizzato nel core per aggiungere le categorie al menu principale.
Marius

1
Scusa, mi sento un idiota, ma come puoi aggiungere più di un menu? Se uso $menu->addChild($node)più di una volta, l'ultimo ha la precedenza sugli altri. Mostra solo un menu (l'ultimo).
pinicio,

17

Perché tutti vogliono sempre scrivere un modulo. L'ho fatto nel mio layout.xmle ha funzionato come un fascino:

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

come aprire quel collegamento in una nuova scheda?
jafar pinjar,

Buona domanda. Trovato qualcosa nel codice. Forse prova questo: <argomento name = "attributi" xsi: type = "array"> <item name = "target" xsi: type = "string"> _ blank </item> </argument> Non testato, ma c'è il opzione attributi disponibile.
Johnny Longneck,

La creazione di un modulo lo rende molto più dinamico. Molti clienti con cui lavoro vogliono fare le cose da soli come in questo caso creando pagine e aggiungendole al menu principale in un ordine specifico.
Roy Jeurissen,

6

Un'altra soluzione al di fuori della creazione di un modulo è la sovrascrittura di topmenu.phtml. Noterò che la soluzione fornita da @Marius è il modo migliore per farlo se intendi che i tuoi collegamenti ereditino le classi di navigazione. Questo viene visualizzato nel menu mobile di Magento, solo senza il CSS corretto. È possibile utilizzare l'argomento css_class per lo stile di conseguenza.

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>

Dove posso trovare un esempio dell'argomento della classe css?
Camdixon,


come si collega il file modello al file xml ..
Sarvesh Tiwari,

6

Questa risposta è fornita da Marius ♦ L'ho appena modificata per aggiungere la categoria figlio nel menu della scheda categoria, puoi fare riferimento alla risposta di Marius ♦. Ho appena modificato il file Topmenu.php secondario per aggiungere la categoria secondaria nella categoria principale

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

È necessario creare un nodo per la categoria padre e per la categoria figlio e successivamente è possibile assegnare la categoria figlio alla categoria padre utilizzando il metodo addChild qui è un esempio

$contactsNode->addChild($warrantyRegistrationNode);

Grazie! non mi rendevo conto che era così facile aggiungere il sottomenu!
Juliano Vargas,

e signore, se voglio mostrare il mio div personalizzato sul collegamento personalizzato che ho aggiunto Topmenu. Come quando passo con il mouse sul collegamento, questo mostra il mio div
Asad Khan,

1

Usando la risposta di Marius sopra ho aggiunto voci di sottomenu. Mostro anche un modo per modificare l'albero prima della creazione dell'html e come modificare direttamente l'html una volta creato. Funziona in Magento 2.1. Aggiorna Topmenu.php con questo:

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

Desideri aggiungere un collegamento alla barra di navigazione principale in <header>
Aggiunta di un collegamento alla pagina CMS, Galleria

Modifica / Inserisci default.xml qui:

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

Aggiungi il seguente codice:

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

Ciò aggiunge un collegamento alla pagina CMS, Galleria, con le seguenti impostazioni:

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

Aggiungi il seguente stile per assicurarti che il nuovo link sia allineato correttamente:

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

Risultati del codice (I prodotti sono configurati come categoria per un esempio)



0

Per coloro che desiderano aggiungere is_activeespressione, in particolare @zed Barbanera che ha chiesto sopra.

Ho usato per collegare il contatto e funzionerà anche con il modulo personalizzato come sto collegando a uno.

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

// (espressione per determinare se la voce di menu è selezionata o meno)

Spero che aiuti chiunque.


0

Questa è anche una buona opzione:

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

Solo per un link al menu di navigazione, non ci sono molti passaggi da raggiungere, ho trovato un breve tutorial su come farlo, implica un tema che sovrascrive il topmenu.phtmlfile dal Magento_Thememodulo: https://linkstraffic.net/adding-custom- menu-item-inside-magento2 / L'ho provato con successo, quindi lo condivido con voi ragazzi.


Benvenuti in Magento SE. Se pubblichi collegamenti in una risposta, assicurati che la risposta sia ancora valida, se il collegamento si interrompe in qualche momento: ad esempio, riepiloga l'articolo collegato o cita le parti pertinenti. Questo è importante perché StackExchange mira ad essere un database della conoscenza, non un forum di supporto che aiuta una persona in questo momento. I futuri visitatori dovrebbero comunque beneficiare delle domande e risposte.
Siarhey Uchukhlebau,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.