Magento 2: dodanie własnej zakładki na stronie produktu
W Magento 2 na stronie produktu mamy zakładki, które odpowiadają za wyświetlanie dodatkowych informacji na temat produktu. W tym wpisie pokaże, jak to działa i jak wygląda dodanie własnej zakładki na stronie produktu.
Zakładki na stronie produktu — jak to działa?
Zacznijmy od konfiguracji layoutu, która za to odpowiada. Na strony produktu, główny plik layoutu to catalog_product_view.xml, którego podstawowa wersja znajduje się w module Magento_Catalog. Fragment konfiguracji odpowiedzialny za konfigurację zakładek na stronie produktu jest następujący:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<block class="Magento\Catalog\Block\Product\View\Details" name="product.info.details" template="Magento_Catalog::product/view/details.phtml" after="product.info.media"> <block class="Magento\Catalog\Block\Product\View\Description" name="product.info.description" as="description" template="Magento_Catalog::product/view/attribute.phtml" group="detailed_info"> <arguments> <argument name="at_call" xsi:type="string">getDescription</argument> <argument name="at_code" xsi:type="string">description</argument> <argument name="css_class" xsi:type="string">description</argument> <argument name="at_label" xsi:type="string">none</argument> <argument name="title" translate="true" xsi:type="string">Details</argument> <argument name="sort_order" xsi:type="string">10</argument> </arguments> </block> <block class="Magento\Catalog\Block\Product\View\Attributes" name="product.attributes" as="additional" template="Magento_Catalog::product/view/attributes.phtml" group="detailed_info"> <arguments> <argument translate="true" name="title" xsi:type="string">More Information</argument> <argument name="sort_order" xsi:type="string">20</argument> </arguments> </block> </block> |
Klasa bloku Magento\Catalog\Block\Product\View\Details, w swoim pliku templaty pobiera listę dzieci, które przynależą do konkretnej grupy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** @var \Magento\Catalog\Block\Product\View\Details $block */ /** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */ ?> <?php if ($detailedInfoGroup = $block->getGroupSortedChildNames('detailed_info', 'getChildHtml')):?> <div class="product info detailed"> <?php $layout = $block->getLayout(); ?> <div class="product data items" data-mage-init='{"tabs":{"openedState":"active"}}'> <?php $hideTabContent = false; ?> <?php foreach ($detailedInfoGroup as $name):?> <?php $html = $layout->renderElement($name); if (!$html || !trim($html)) { continue; } $alias = $layout->getElementAlias($name); $label = $block->getChildData($alias, 'title'); ?> <div class="data item title <?= !$hideTabContent ? 'active' : ''?>" data-role="collapsible" id="tab-label-<?= $block->escapeHtmlAttr($alias) ?>"> <a class="data switch" tabindex="-1" data-toggle="trigger" href="#<?= $block->escapeUrl($alias) ?>" id="tab-label-<?= $block->escapeHtmlAttr($alias) ?>-title"> <?= /* @noEscape */ $label ?> </a> </div> <div class="data item content" aria-labelledby="tab-label-<?= $block->escapeHtmlAttr($alias) ?>-title" id="<?= $block->escapeHtmlAttr($alias) ?>" data-role="content"> <?= /* @noEscape */ $html ?> </div> <?= $hideTabContent ? /* @noEscape */ $secureRenderer->renderStyleAsTag( 'display: none;', '#' . $block->escapeHtmlAttr($alias) ) : '' ?> <?php $hideTabContent = true; ?> <?php endforeach;?> </div> </div> <?php endif; ?> |
Za zwrócenie listy bloków odpowiedzialnych za renderowanie danej zakładki, odpowiada metoda getGroupSortedChildNames():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/** * Get sorted child block names. * * @param string $groupName * @param string $callback * @throws \Magento\Framework\Exception\LocalizedException * * @return array * @since 103.0.1 * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getGroupSortedChildNames(string $groupName, string $callback): array { $groupChildNames = $this->getGroupChildNames($groupName); $layout = $this->getLayout(); $childNamesSortOrder = []; foreach ($groupChildNames as $childName) { $alias = $layout->getElementAlias($childName); $sortOrder = (int)$this->getChildData($alias, 'sort_order') ?? 0; $childNamesSortOrder[$childName] = $sortOrder; } asort($childNamesSortOrder, SORT_NUMERIC); return array_keys($childNamesSortOrder); } |
Dodanie nowej zakładki wymaga od nas stworzenia nowego bloku oraz dodania odpowiedniej konfiguracji do pliku layoutu.
Dodanie własnej zakładki
Dodamy teraz własną zakładkę na stronę produktu. W konfiguracji layoutu potrzebujemy umieścić własną klasę bloku wewnątrz referencji do klasy Magento\Catalog\Block\Product\View\Details. Standardowo tworzymy klasę bloku, templatę do niej i dołączamy ją do layoutu. Jak stworzyć przykładowy blok znajdziesz w notce: Tworzenie nowego bloku w Magento 2.
Następnym krokiem jest stworzenie pliku layoutu catalog_product_view.xml, który umieszczamy w podkatalogu view/frontend/layout modułu. Przykładowa konfiguracja może wyglądać następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0"?> <page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="product.info.details"> <block class="Anna\CustomTab\Block\Custom" name="custom_tab" as="custom_tab" template="Anna_CustomTab::product/view/hello.phtml" group="detailed_info"> <arguments> <argument name="title" xsi:type="string">Custom Tab</argument> <argument name="sort_order" xsi:type="string">15</argument> </arguments> </block> </referenceContainer> </body> </page> |
Na przedstawionym przykładzie widzimy, że węzeł <block> powinien zawierać takie atrybuty jak:
- as — alias dla naszej nazwy bloku, pamiętając o tym, że nazwa powinna być unikalna,
- group — nazwę grupy, do której należy blok. W omawianym przykładzie powinna to być wartość „detailed_info„.
Dla samej konfiguracji naszej klasy bloku potrzebowaliśmy określić następujące argumenty:
- title — do zdefiniowana wyświetlanej nazwy dla naszej zakładki,
- sort_order — tu podajemy wartość liczbową do sortowania. Zakładki wyświetlane są w kolejności rosnącej.
Ostatnim krokiem, jak zwykle, jest wyczyszczenie cache’a, aby zobaczyć efekt końcowy: