This article shows how you can add custom link or tab in the Customer account sidebar section.
I will also show how you add/show your custom page when you click on the newly added custom link in the customer account sidebar.
So, basically, we will be adding a custom link and linking it to a custom page. The custom page will also contain the customer account sidebar displayed.
Here’s how you do it:
Suppose, your module name is YourNamespace_YourModule
.
1) Create customer_account layout XML file
Create the layout file at this location:
app/code/YourNamespace/YourModule/view/frontend/layout/customer_account.xml
Here, I have added two ways (one is commented out) to add the custom links in the customer account navigation sidebar.
– One will add the links at the bottom of the sidebar list
– The other has the sortOrder feature which can sort the custom links in any custom order
<?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>
<referenceBlock name="customer_account_navigation">
<!-- Add menu to the end of the sidebar -->
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
<arguments>
<argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>
<argument name="label" xsi:type="string">Your First Link</argument>
</arguments>
</block>
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
<arguments>
<argument name="path" xsi:type="string">yourmodule/yoursecondlink/index</argument>
<argument name="label" xsi:type="string">Your Second Link</argument>
</arguments>
</block>
<!-- Add menu in the sidebar with sort order -->
<!--
<block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-your-first-link">
<arguments>
<argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>
<argument name="label" xsi:type="string">Your First Link</argument>
<argument name="sortOrder" xsi:type="number">250</argument>
</arguments>
</block>
<block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-your-second-link">
<arguments>
<argument name="path" xsi:type="string">yourmodule/yoursecondlink/index</argument>
<argument name="label" xsi:type="string">Your Second Link</argument>
<argument name="sortOrder" xsi:type="number">260</argument>
</arguments>
</block>
-->
</referenceBlock>
</body>
</page>
Showing Active Menu Link when clicked
There was one issue with showing the active menu link in the customer sidebar navigation.
My custom link was clicked and my custom page was displayed but the custom link was not highlighted. Highlighting the active menu link makes it easy to figure out on which page we are in.
To fix this issue, I had to remove the “action” path in the XML code.
In the above XML code, you can see that I have defined my custom menu path as:
<argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>
Here,
yourmodule = my module name
yourfirstlink = my module’s controller name
index = my controller’s action
I removed the ‘index’ text from the path, like this:
<argument name="path" xsi:type="string">yourmodule/yourfirstlink</argument>
Then, the active link issue was solved. Now, when I click on my custom menu link, it becomes highlighted.
TIP:
You can also remove customer sidebar menu items by writing the remove code in the customer_account.xml
file you created inside your custom module.
<?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>
<referenceBlock name="customer-account-navigation-wish-list-link" remove="true"/>
</body>
</page>
2) Create your module’s routes.xml file
The routes.xml
file maps which module to use for a URL with a specific frontName.
For frontend URL mapping, we create routes file inside etc/frontend
folder.
Similarly, for backend URL mapping, we create routes file inside etc/adminhtml
folder.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="productsinrange" frontName="productsinrange">
<module name="YourNamespace_YourModule" />
</route>
</router>
</config>
3) Create your module’s layout XML file
We have defined two links. The paths of the links defined in the above XML code are:
– yourmodule/yourfirstlink/index
– yourmodule/yoursecondlink/index
These paths indicate the controller classpath of your module. These paths should also match the layout XML file name. Hence, we create two different XML files for each specified paths.
<update handle="customer_account"/>
Note:
This code is important in the below XML files. Without this code, the customer sidebar navigation menu will not appear on your custom pages.
We specify our custom Block class and link it to our firstlink phtml file.
<?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">
<update handle="customer_account"/>
<head>
<title>
Your First Link
</title>
</head>
<body>
<referenceContainer name="content">
<block class="YourNamespace\YourModule\Block\YourBlock" name="yourmodule.firstlink.index" template="YourNamespace_YourModule::yourfirstlink/index.phtml" cacheable="false" />
</referenceContainer>
</body>
</page>
We specify a general Template block class and link it to our second link phtml file.
<?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">
<update handle="customer_account"/>
<head>
<title>
Your Second Link
</title>
</head>
<body>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="yourmodule.secondlink.index" template="YourNamespace_YourModule::yoursecondlink/index.phtml" cacheable="false" />
</referenceContainer>
</body>
</page>
4) Create Controller class files
We have specified two controller paths in the layout XML file. So, we create two controller classes.
<?php
namespace YourNamespace\YourModule\Controller\YourFirstLink;
class Index extends \Magento\Framework\App\Action\Action
{
/**
* @var \Magento\Framework\View\Result\PageFactory
*/
protected $resultPageFactory;
/**
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\View\Result\PageFactory resultPageFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
/**
* Default customer account page
*
* @return void
*/
public function execute()
{
return $this->resultPageFactory->create();
}
}
?>
<?php
namespace YourNamespace\YourModule\Controller\YourSecondLink;
class Index extends \Magento\Framework\App\Action\Action
{
/**
* @var \Magento\Framework\View\Result\PageFactory
*/
protected $resultPageFactory;
/**
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\View\Result\PageFactory resultPageFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
/**
* Default customer account page
*
* @return void
*/
public function execute()
{
return $this->resultPageFactory->create();
}
}
?>
5) Create Block class file
For our firstlink, we had defined our own custom Block class. So, we create the Block class now.
<?php
namespace YourNamespace\YourModule\Block;
class YourBlock extends \Magento\Framework\View\Element\Template
{
public function __construct(
\Magento\Backend\Block\Template\Context $context,
array $data = []
)
{
parent::__construct($context, $data);
}
public function getHelloWorld()
{
return 'Hello World';
}
}
?>
6) Create Template files
<h2>
<?php echo $block->getHelloWorld(); ?>
</h2>
echo 'My First Link Page';
echo 'My Second Link Page';
Hope this helps. Thanks.