Changing a layout XML of a Magento 2 module

In order to customize the layout to your own requirements, you can just add it to your theme and make the required changes. In order to change a layout from a Magento 2 module, you will need to locate the module and layout handle that you want to alter.

The following steps will show you how to change elements defined in a layout file to match your desired design:

  1. Create the layout handle file for the Magento_Catalog module:

app/design/frontend/Genmato/default/Magento_Catalog/layout/catalog_product_view.xml


<?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>
<move element="product.info.stock.sku" destination="product.info.price" after="product.price.final"/>
<move element="product.info.review" destination="product.info.main" before="product.info.price"/>

<remove name="report.bugs"/>
</body>
</page>

  1. Upload the file to your Magento 2 installation and refresh the cache:
    bin/magento cache:clean
  2. Next, generate the static content:
    bin/magento setup:static-content:deploy
    Make sure that you remove your theme-generated files from the following locations:
    pub/static/frontend/ var/view_preprocessed/css/frontend/
    Otherwise, the changes in the Less files in your theme will not be used as the preprocessor checks if there is already a generated CSS file available.
  3. Navigate to a product page to see the changed position of stock info and SKU

How does it work…

In the layout XML files, there are a few commands available to change the way in which a page is rendered. Here is a short description of every available command.

<container>

A container defines a structural layout block that does not produce its own content and can hold other blocks and/or containers. The output of the content generated by the children can be rendered in any valid HTML 5 tag with the option to specify an ID or class used for the element. Here is an example of the product.info.stock.sku container and the blocks that are added:


<container name="product.info.stock.sku" label="Product auxiliary info" htmlTag="div" htmlClass="product-info-stock-sku">
<container name="product.info.type" before="-"/>
<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.sku" template="product/view/attribute.phtml" after="product.info.type">
<arguments>
<argument name="at_call" xsi:type="string">getSku</argument>
<argument name="at_code" xsi:type="string">sku</argument>
<argument name="css_class" xsi:type="string">sku</argument>
<argument name="at_label" xsi:type="string">default</argument>
<argument name="add_attribute" xsi:type="string">itemprop="sku"</argument>
</arguments>
</block>
</container>

A block generates content from the specified class and assigned template file. In the arguments of the block, it’s possible to specify the load order using the before and after tags. Depending on the class specified, it’s possible to pass information using the <argument> tag:


<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.overview" template="product/view/attribute.phtml" group="detailed_info" after="product.info.extrahint">
<arguments>
<argument name="css_class" xsi:type="string">overview</argument>
</arguments>
</block>

Arguments passed to the class can be the class methods or magic setters/getters and can be accessed in the template. The preceding css_class argument assigned can be requested in the template through $this->getCssClass(); .

referenceContainer/referenceBlock

In order to add a block or container to an element specified in another layout file, you will need to reference this element. This way it’s possible to add blocks to both the main content area and sidebar in the same layout file:


<referenceContainer name="product.info.type">
<block class="Magento\Catalog\Block\Product\View\Type\Simple" name="product.info.simple" as="product_type_data" template="product/view/type/default.phtml"/>
<container name="product.info.simple.extra" after="product.info.simple" as="product_type_data_extra" label="Product Extra Info"/>
</referenceContainer>

move

The move command allows you to change the location where the element is shown to another element. In this recipe, the SKU information was placed after the product.price.final block in the product.info.price container, where the default location would be the first block shown.

remove

The remove command will remove the block referenced with the name parameter; this will cause it not to be rendered on the page.

update

With the update instruction, it is possible to include a layout handle. This allows you to include
a set of instructions defined once to multiple layouts. An example of this is the customer
account; here, all account menu options for logged in users are defined in the customer_account.xml layout file:


<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Customer My Account (All Pages)" design_abstraction="custom">
<body>
<attribute name="class" value="account"/>
<referenceContainer name="sidebar.main">

<block class="Magento\Framework\View\Element\Html\Links" name="customer_account_navigation" before="-" template="Magento_Customer::account/navigation.phtml">
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-account-link">
<arguments>
<argument name="label" xsi:type="string" translate="true">Account Dashboard</argument>
<argument name="path" xsi:type="string">customer/account</argument>
</arguments>
</block>
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-account-edit-link">
<arguments>
<argument name="label" xsi:type="string" translate="true">Account Information</argument>
<argument name="path" xsi:type="string">customer/account/edit</argument>
</arguments>
</block>
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-address-link">
<arguments>
<argument name="label" xsi:type="string" translate="true">Address Book</argument>
<argument name="path" xsi:type="string">customer/address</argument>
</arguments>
</block>
</block>
</referenceContainer>
</body>
</page>

This file is then included in the customer_account_index.xml layout (and other pages using this menu):


<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="customer_account"/>
<body>
<referenceBlock name="page.main.title">

<action method="setPageTitle">
<argument translate="true" name="title" xsi:type="string">My Dashboard</argument>
</action>
</referenceBlock>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="customer_account_dashboard_top" as="top"/>
<block class="Magento\Customer\Block\Account\Dashboard\Info" name="customer_account_dashboard_info" as="info" template="account/dashboard/info.phtml" cacheable="false"/>
<block class="Magento\Customer\Block\Account\Dashboard\Address" name="customer_account_dashboard_address" as="address" template="account/dashboard/address.phtml" cacheable="false"/>
</referenceContainer>
</body>
</page>

Overriding template files

Templates are loaded in the following order:

  1. Active theme, where it looks for the file in <theme>/<Module_Namespace>_<Module_name>/template/<requested template> .
  2. Parent theme(s) (until no parent is found).
  3. Module directory.

In order to override a template in your theme, it is possible to create your own version of the file. For example, to replace the left navigation file from the catalog module, copy the file from the original location <Magento_Catalog path>/view/frontend/templates/navigation/left.phtml to your theme location <theme>/Magento_Catalog/templates/navigation/left.phtml . Here, you can apply your own changes necessary to suit your theme.

Another option is to change the template file assigned through a layout change; this can be useful if you want to change the template only for a specific product, category, or other page handle available. For this, you need to create a new layout file based on the file handle where you reference the block where you want to update the template. Using the <action> method, setTemplate , you can now specify the new template you want to use:


<referenceBlock name="[blockname]">
<arguments>
<argument name="template" xsi:type="string">[Module name]::[path to template]</argument>
</arguments>
</referenceBlock>

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s