Now let’s come back to frontend development. Earlier we created a controller where I wrote a “Hello World” statement to show you that the controller is working. But in Magento, we don’t write HTML code in the controller.
To show HTML content we use .phtml files in Magento. These .phtml files are called template files.
To map the controller with .phtml files we use layout files. The layout files are of .xml type. As all of these are related to viewing the page. So it makes sense to put them in a different folder, which is called the view folder.
First, we need to modify the controller file, Controller/Manage/Add.php
Updated code for Controller/Manage/Add.php file
<?php namespace Webkul\BlogManager\Controller\Manage; use Magento\Customer\Controller\AbstractAccount; use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Add extends AbstractAccount { /** * @var PageFactory */ private $resultPageFactory; /** * Dependency Initilization * * @param Context $context * @param PageFactory $resultPageFactory */ public function __construct( Context $context, PageFactory $resultPageFactory ) { $this->resultPageFactory = $resultPageFactory; parent::__construct($context); } /** * Provides content * * @return \Magento\Framework\View\Result\Page */ public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->getConfig()->getTitle()->set(__('Add Blog')); $layout = $resultPage->getLayout(); return $resultPage; } }
Here we are using \Magento\Framework\View\Result\PageFactory class to initialize the layout. With this we can configure the page, here we have set the Title of the page. And after calling the getLayout() method to process the layout file, we returned the result page.
Layout
Now if you notice we have not explicitly mentioned the layout file name in the controller. So Magento will look for the layout file with the name routerId_controllerName_actionName.xml. If we want then we can explicitly give like,
$resultPage->addHandle('some_other_layout');
For the layout file, we need to create a view/frontend/layout folder under the module directory. In the layout folder, we need to create a layout file with the name blogmanager_manage_add.xml. If you remembered we used blogmanager as our router id.
It’s common practice to use routerId as the same as frontName because then the layout file name will be similar to the URL.
Code for view/frontend/layout/blogmanager_manage_add.xml file
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <block class="Magento\Framework\View\Element\Template" name="blogmanager.blog.add" template="Webkul_BlogManager::add.phtml" /> </referenceContainer> </body> </page>
The body node refers to that we are modifying contents within the body tag of the HTML. The page layout in Magento is made out of multiple containers. And the container can have nested containers. The innermost containers have blocks in them and each block can have child blocks.
Layout Types
As you can see in the page tag we have used the layout attribute with the value 1column. Magento supports different types of layouts such as,
i) 1coumn
ii) 2columns-left
iii) 2columns-right
iv) 3columns
For simplicity, you can think of the header, footer, and main content as individual containers. However, Magento’s layout structure is much more complex, which helps us to modify any component.
For the 2columns-left layout, the main content will have two sub-containers, one for content and another on the left side as a sidebar container.
With the referenceContainer tag, we can target any container, here we are targeting the main container whose name is content. You can find more container and block names in the vendor/magento/module-theme/view/frontend/layout/default.xml file.
Inside the container, we are calling our phtml file with a block tag. Here we are using the default template block class Magento\Framework\View\Element\Template but we can create our own block class if we have to pass some data into the phtml.
We will see more about the Block class in the next blog. The block tag has a name attribute, we can use any sensible name here to identify that block.
Templates
The interesting part in the block tag is template=”Webkul_BlogManager::add.phtml”, this represents the path of the template file. The first part of :: is the module name and the second part is the path in reference to the view/frontend/templates folder.
As in the path we have given the phtml file name so we can directly create add.phtml file under the view/frontend/templates folder.
Code for view/frontend/templates/add.phtml file
<div class="blog-container"> <form class="blog-form"> Title: <input type="text" name="title"/> Content: <textarea name="content"></textarea> <button type="submit">Submit</button> </form> </div>
After writing all of this code we have to run the di compile command. And now if you browse the URL you will see the page,
Please try out different layout types on your own.
If you make some changes in the template file and can not find it when reloading the page then please flush the cache.
php bin/magento cache:flush
Enhancing
We are aiming to create a blog portal where customers can write blogs. So it makes much more sense that the page should appear like other customer account pages and instead of manually entering the URL we should have a menu in the customer navigation.
To add the customer navigation menu we will follow the “Magento2 – Add New Link in My Account Navigation Panel” blog. We have to create a customer_account.xml file under the view/frontend/layout folder. Magento already has this XML file we are just appending our code to it.
Code for view/frontend/layout/customer_account.xml file
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="customer_account_navigation"> <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-blog-add" after="-" > <arguments> <argument name="label" xsi:type="string" translate="true">Add Blog</argument> <argument name="path" xsi:type="string">blog/manage/add</argument> </arguments> </block> </referenceBlock> </body> </page>
Now let’s modify our already created blogmanager_manage_add.xml file to match the customer account page structure.
Updated code for view/frontend/layout/blogmanager_manage_add.xml file
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="customer_account"/> <body> <referenceContainer name="content"> <block class="Magento\Framework\View\Element\Template" name="blogmanager.blog.add" template="Webkul_BlogManager::add.phtml" /> </referenceContainer> </body> </page>
Here you can see that we have removed the layout type and added the <update handle=”customer_account”/> tag.
Basically, it says that copies everything from the customer_account.xml, so it will copy all the structure from customer_account.xml which acts as a base for every customer account-related page.
Now when we di compile and reload we will see something like,
Folder structure till now,
PS. Please run the di compile command if you create a new file, modify any .xml file, or make changes in the constructor of a class.
Sometimes running di compile might not have any effect then we should explicitly remove the generated/code folder by running rm -rf generated/code from the Magento root directory. Please be careful while running the rm -rf command.
Next Blog -> Magento 2 Development 09: Form Validation and Saving Data
Previous Blog -> Magento 2 Development 07: Model, Resource Model and Collection
Be the first to comment.