Intro To Magento 2, Part 5: Layouts and Frontend Elements

Now that we’ve jumped into custom blocks, let’s talk about ways to include them in the web site. I’m not talking about simply creating a custom page. We can add navigation menus and include them in menus of other areas of the web site. Layouts are an easy way to do this.

Let’s continue on with our Danjoseph_Helloworld custom module. We are going to integrate our My Greetings page with the customer account area by adding it to the navgiation menu. We will also add a navigation menu to the hello world page.

1. What’s new to add layout elements?

Think back to the very first layout file we created. These are simply XML files that tell Magento what elements to include and which templates to associate with them. They’re not only for associating a block class with a template. You can use them to include other blocks and elements of your web site.

Here is our new code base:

app/code/Danjoseph/Helloworld/Blocks/Helloworld.php
app/code/Danjoseph/Helloworld/Controller/Index/Index.php
app/code/Danjoseph/Helloworld/Controller/Crud/Create.php
app/code/Danjoseph/Helloworld/Controller/Crud/Update.php
app/code/Danjoseph/Helloworld/Controller/Crud/Delete.php
app/code/Danjoseph/Helloworld/etc/module.xml
app/code/Danjoseph/Helloworld/etc/frontend/routes.xml
app/code/Danjoseph/Helloworld/Model/Hello.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Hello.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Hello/Collection.php
app/code/Danjoseph/Helloworld/view/frontend/layout/customer_account.xml
app/code/Danjoseph/Helloworld/view/frontend/layout/helloworld_index_index.xml
app/code/Danjoseph/Helloworld/view/frontend/templates/helloworld.phtml
app/code/Danjoseph/Helloworld/Setup/InstallSchema.php
app/code/Danjoseph/Helloworld/registration.php

We’re simply adding one additional file and re-factoring another:

app/code/Danjoseph/Helloworld/view/frontend/layout/customer_account.xml
app/code/Danjoseph/Helloworld/view/frontend/layout/helloworld_index_index.xml

This will allow us to grab the customer account area layout and use elements from it.

2. What does our new layout look like?

Let’s take a look at what your layout file look like.

app/code/Danjoseph/Helloworld/view/frontend/layout/customer_account.xml

<body>
    <referenceBlock name="customer_account_navigation">
        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-my-greetings">
            <arguments>
                <argument name="path" xsi:type="string">helloworld/index/index</argument>
                <argument name="label" xsi:type="string" translate="true">My Greetings</argument>
            </arguments>
        </block>
    </referenceBlock>
</body>

Let’s break this down a little bit.

customer_account.xml is the layout for the customer account area.

In the referenceBlock line, we’re calling customer_account_navigation.

Next, we’re adding our link. You can add as many or few of these as you want.

<argument name="path" xsi:type="string">helloworld/index/index</argument>

This is the path to our module. The path string goes “modulename/controller/action”. This also matches our URL.

http://magento.danjoseph.me/helloworld/index/index

Now let’s clear our cache and head to the customer account dashboard.

% php bin/magento cache:clean

You’ll notice at the very top of the left navigation is “My Greetings”. Click on that, and you will be at your My Greetings page. Also please note that you are not in the customer_account.xml layout format anymore. We need to modify our original helloworld_index_index.xml layout file and include some new things.

app/code/Danjoseph/Helloworld/view/frontend/layout/helloworld_index_index.xml

<?xml version="1.0"?>
<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-my-account-greetings">
                    <arguments>
                        <argument name="label" xsi:type="string" translate="true">My Greetings</argument>
                        <argument name="path" xsi:type="string">helloworld/index/index</argument>
                    </arguments>
                </block>
                <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 class="Magento\Framework\View\Element\Template" ifconfig="magento_invitation/general/enabled" template="Magento_Theme::template.phtml" name="customer-account-navigation-magento-invitation-link-container">
                    <block class="Magento\Framework\View\Element\Html\Link\Current" ifconfig="magento_invitation/general/enabled_on_front" name="customer-account-navigation-magento-invitation-link">
                        <arguments>
                            <argument name="path" xsi:type="string">magento_invitation/</argument>
                            <argument name="label" xsi:type="string">My Invitations</argument>
                        </arguments>
                    </block>
                </block>
            </block>
        </referenceContainer>
        <referenceContainer name="content">
            <block class="Danjoseph\Helloworld\Block\Helloworld" name="my_greetings" template="Danjoseph_Helloworld::helloworld.phtml" />
        </referenceContainer>
    </body>
</page>

Now clean your cache and reload the page.

% php bin/magento cache:clean

There is your My Greetings page with the customer account dashboard navigation items.

I kept this pretty basic with only a few menu options from the left navigation. Notice I included our helloworld block class and template at the bottom.

You have a path and label for each argument. I have included a handful of the account dashboard navigation items.

Take a few minutes to read that file over. You can add any block to the menu.

3. Is that it?

Yes!

You can go here to see a working model, you’ll need to create an account first:

http://magento.danjoseph.me
http://magento.danjoseph.me/helloworld/index/index

Please note: I’ve disabled all crud functionality for security purposes. We’ll revisit this in a future part with security and personalization.

Now you’re ready to create layout files of your own. You have all the tools to include blocks to create navigation menus, widgets, and other custom blocks you’ve written.

Written by Dan
Welcome to my blog! Here you'll find my collection of bible study lessons, book reviews, and other posts I feel inspired to write. I am a Christian currently serving at First Baptist Church of Northville in Northville, MI.