[vc_row][vc_column][vc_column_text]
In Magento 2, there are two main methods for overriding a template. The basic set of instructions is the same for all types of layout files.
- Theme file path
- Layout block argument
The template file path method is used when building your theme, and the layout method is used when creating a module. These are the easiest of methods to use. Later in the article, I will cover the other two methods:
- Class preferences
- Plugins
Use these layout instructions to:
- move a page element to another parent element
- add content
- remove a page element
Page layout files conventional location
Page layouts must be located as follows:
- Module page layouts:
<module_dir>/view/frontend/page_layout
- Theme page layouts:
<theme_dir>/<Namespace>_<Module>/page_layout
<layout id="layout_file_name">
. For example, the2columns-left.xml
page layout is declared as the following:<layout id="2columns-left"/>
Page layouts declaration
To be able to use a page layout for rendering html, you need to declare it in XML.
Layout declaration files can be located in one of the following locations:
- Module layout declarations:
<module_dir>/view/frontend/layout/
- Theme layout declaration:
<theme_dir>/<Namespace>_<Module>/layout
See the Magento 2 devdocs for further details on page layouts.
Allowed layout instructions:
<container>
- A structure without content that holds other layout elements such as blocks and containers. Containers render their child elements during view output generation. It can be empty or it can contain an arbitrary set of
<container>
and<block>
elements.
- A structure without content that holds other layout elements such as blocks and containers. Containers render their child elements during view output generation. It can be empty or it can contain an arbitrary set of
<container name="div.sidebar.additional" htmlTag="div" htmlClass="sidebar sidebar-additional" after="div.sidebar.main">
<container name="sidebar.additional" as="sidebar_additional" label="Sidebar Additional"/>
</container><referenceBlock>
and<referenceContainer>
Applied to the corresponding
<block>
or<container>
. For example, if you make a reference by<referenceBlock name="right">
, you’re targeting the block<block name="right">
.
- To pass parameters to a block use the
<argument></argument>
instruction. <referenceBlock name="top.links" remove="true" />
removes top links from the header- This implementation allows you to cancel removal of a block or container in your layout by setting remove attribute value to
true
- This implementation allows you to cancel removal of a block or container in your layout by setting remove attribute value to
-
<referenceContainer name="header.container" htmlClass="main-header"> <container name="header-wrapper2" label="Page Header" as="header-wrapper2" htmlTag="div" htmlClass="header content"> <block class="Magento\Theme\Block\Html\Header" name="desktop.header" as="desktop.header" before="-" template="Magento_Theme::html/header.phtml"> </block> <block class="Magento\Theme\Block\Html\Header" name="mobile.header" as="mobileHeader" before="-" template="Magento_Theme::html/mobile-header.phtml"> </block> </container> </referenceContainer>
- In this instance within default.xml of Magento_Theme, I have extended the layout by creating a custom reference container header.container with assigned html classes to it. Within this container, I have called block class Magento\Theme\Block\Html\Header from the Magento_Theme module, gave this class a new alias and defined the template to render. Extending this layout ensures, the other child elements are rendered and also render the newly defined elements. This is covered in further detail below.
<move>
- Sets the declared block or container element as a child of another element in the specified order.
<move element="name.of.an.element" destination="name.of.destination.element" as="new_alias" after="name.of.element.after" before="name.of.element.before"/>
<move element="minicart" destination="desktop.header" after="_" />
- This moves minicart to target parent element, desktop.header.
before
andafter
attributes of<block>
- Allows changing elements’ order within one parent.
after="_"
declares that minicart will render after all the other child elements in the block.
- Allows changing elements’ order within one parent.
<update>
- Includes a certain layout file. Used as follows:
<update handle="{name_of_handle_to_include}"/>
- Includes a certain layout file. Used as follows:
Set the template used by a block
There are two ways to set the template for a block:
- using the
template
attribute - using the
<argument>
instruction
Both approaches are demonstrated in the following examples of changing the template of the page title block.
Example 1:
<referenceBlock name="page.main.title" template="%Namespace_Module::new_template.phtml%">
Example 2:
<referenceBlock name="page.main.title"> <arguments> <argument name="template" xsi:type="string">%Namespace_Module::new_template.phtml%</argument> </arguments> </referenceBlock>
In both examples, the template is specified according to the following:
Namespace_Module
: defines the module the template belongs to. For example,Magento_Catalog
.new_template.phtml
: the path to the template relatively to thetemplates
directory.- It can be either
<module_dir>/view/<area>/templates
or<theme_dir>/<Namespace_Module>/templates
.
- It can be either
Display CMS/static blocks in Magento 2
In XML File:
<referenceContainer name="content"> <block class="Magento\Cms\Block\Block" name="block_identifier"> <arguments> <argument name="block_id" xsi:type="string">block_identifier</argument> </arguments> </block> </referenceContainer>
In Phtml File:
<?php echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('block_identifier')->toHtml();?>
in CMS Content:
{{block class="Magento\\Cms\\Block\\Block" block_id="block_identifier"}}
Creating a simple module
There will be times when you need to add additional components to your store. In this case we are adding a bootstrap.js library
Create Module Folder Structure:
app / code / [Vendor] / [ModuleName]
app / code / [Vendor] / [ModuleName] / etc
app / code / [Vendor] / [ModuleName] / view / frontend / layout
Create Module Files:
app / code / [Vendor] / [ModuleName] / registration.php
app / code / [Vendor] / [ModuleName] / etc / module.xml
app / code / [Vendor] / [ModuleName] / view / frontend / requirejs-config.js
app / code / [Vendor] / [ModuleName] / view / frontend / layout / default.xml
app / code / [Vendor] / [ModuleName] / view / frontend / layout / default_head_blocks.xml
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'[Vendor]_[ModuleName]',
__DIR__
);
module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../vendor/magento/framework/Module/etc/module.xsd">
<module name="[Vendor]_[ModuleName]" setup_version="0.0.1"/>
</config>
requirejs-config.js
var config = {
paths: {
"jquery.bootstrap": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min"
},
shim: {
'jquery.bootstrap': {
'deps': ['jquery']
}
}
};
default.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../vendor/magento/framework/Module/etc/module.xsd">
<referenceBlock name="head">
<block class="Magento\Theme\Block\Html\Head\Script" name="requirejs" before="-">
<arguments>
<!-- RequireJs library enabled -->
<argument name="file" xsi:type="string">requirejs/require.js</argument>
</arguments>
</block>
<!-- Special block with necessary config is added on the page -->
<block class="Magento\RequireJs\Block\Html\Head\Config" name="requirejs-config" after="requirejs"/>
</referenceBlock>
</page>
default_head_blocks.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../vendor/magento/framework/Module/etc/module.xsd">
<head>
<css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" src_type="url"/>
<css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" src_type="url"/>
</head>
</page>
Enable Module (SSH to magento root):
php -f bin/magento module:enable --clear-static-content [Vendor]_[ModuleName]
php -f bin/magento setup:upgrade
Deploy static resources (SSH to magento root):
php bin/magento setup:static-content:deploy
RequireJS will not load any javascript module source file until someone uses that javascript module as a dependency.
Example usage in CMS Page:
<script type="text/javascript"> requirejs(['jquery', 'jquery.bootstrap'], function (jQuery, jQueryBootstrap) { jQuery('.carousel').carousel(); }); </script>
Example usage of custom js being called by theme:
require(['jquery', 'jquery.bootstrap'], function ($) { $("li.panel a").click(function () { //do something }); });
How to call a custom JS file in your theme: in your child theme default.xml head section, declare your custom theme JS to render like the same below.
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <link src="js/Mytheme.js"/> </head> </page>
Conclusion
In this 3 part blog series, Super Guide to Theming in Magento 2, I have covered creating and installing custom storefront themes for Magento 2. I have covered M2’s content rendering process, and explained the view layer of the system and how to extend it to build a theme efficiently. I hope that you have found this series to be informative and helpful in your future M2 frontend projects!
You can always revisit Super Guide to Theming Part 1 as a reference for declaring a child theme and setting up Magento 2 via composer and Super Guide to Theming Part 2, that covers, customizing layout illustration such as moving blocks, setting templates for blocks and creating custom modules for theming will cover extending, overriding and customizing our theme via <Namespace_Module>(s) and xml. Look forward to more posts and tutorials about Magento 2 from Jamersan!
[/vc_column_text][/vc_column][/vc_row]