Magento 2 Create Admin Button

Besides the primary purpose for task-based navigation, buttons are also used for calls to action. Many Magento 2 users are confused about adding a button in Magento 2 backend and calling a simple PHP method when clicking on it. In fact, this task can be done easily and quickly. In this post, I will describe the solution on an example of an extension from Mageplaza.

Let’s explore how to create an admin button in Magento 2 through these below steps together!

Step 1: Add A Button As A Field In The Configuration File

Firstly, you need to add a button as a field in the Configuration file (mageplaza_collect as an example):

app/code/Mageplaza/HelloWorld/etc/adminhtml/system.xml

<?xml version="1.0"?>
<!--
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Core
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */
 -->
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <tab id="mageplaza" sortOrder="2001">
            <label>Mageplaza</label>
        </tab>
        <section id="mageplaza_helloworld" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
            <label>Hello World</label>
            <tab>mageplaza</tab>
            <resource>Mageplaza_HelloWorld::config</resource>
            <group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>General</label>
                <field id="mageplaza_collect" translate="label comment" type="button" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
                    <frontend_model>Mageplaza\HelloWorld\Block\System\Config\Collect</frontend_model>
                    <label>Collect all available data (in separate table)</label>
                </field>
            </group>
        </section>
    </system>
</config>

Step 2: Create The Field-Button

Please use the frontend Mageplaza\HelloWorld\Block\System\Config\Collect module to draw the field-button. Here is how you can create it:

app/code/Mageplaza/HelloWorld/Block/System/Config/Collect.php

<?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Core
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */

namespace Mageplaza\HelloWorld\Block\System\Config;

use Magento\Backend\Block\Template\Context;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;

class Collect extends Field
{
    /**
     * @var string
     */
    protected $_template = 'Mageplaza_HelloWorld::system/config/collect.phtml';

    /**
     * @param Context $context
     * @param array $data
     */
    public function __construct(
        Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * Remove scope label
     *
     * @param  AbstractElement $element
     * @return string
     */
    public function render(AbstractElement $element)
    {
        $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
        return parent::render($element);
    }

    /**
     * Return element html
     *
     * @param  AbstractElement $element
     * @return string
     */
    protected function _getElementHtml(AbstractElement $element)
    {
        return $this->_toHtml();
    }

    /**
     * Return ajax url for collect button
     *
     * @return string
     */
    public function getAjaxUrl()
    {
        return $this->getUrl('mageworx_alsobought/system_config/collect');
    }

    /**
     * Generate collect button html
     *
     * @return string
     */
    public function getButtonHtml()
    {
        $button = $this->getLayout()->createBlock(
            'Magento\Backend\Block\Widget\Button'
        )->setData(
            [
                'id' => 'collect_button',
                'label' => __('Collect Data'),
            ]
        );

        return $button->toHtml();
    }
}

This is a typical field model.

Note

  • The button is created using the getButtonHtml() method.
  • To get a URL, please use getAjaxUrl() method.

Step 3: Create A Template

In this step. you need to create a template: app/code/MageWorx/AlsoBought/view/adminhtml/templates/system/config/collect.phtml

<?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Core
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */
?>
<?php /* @var $block \Mageplaza\HelloWorld\Block\System\Config\Collect */ ?>

<script>
    require([
        'jquery',
        'prototype'
    ], function(jQuery){

        var collectSpan = jQuery('#collect_span');

        jQuery('#collect_button').click(function () {
            var params = {};
            new Ajax.Request('<?php echo $block->getAjaxUrl() ?>', {
                parameters:     params,
                loaderArea:     false,
                asynchronous:   true,
                onCreate: function() {
                    collectSpan.find('.collected').hide();
                    collectSpan.find('.processing').show();
                    jQuery('#collect_message_span').text('');
                },
                onSuccess: function(response) {
                    collectSpan.find('.processing').hide();

                    var resultText = '';
                    if (response.status > 200) {
                        resultText = response.statusText;
                    } else {
                        resultText = 'Success';
                        collectSpan.find('.collected').show();
                    }
                    jQuery('#collect_message_span').text(resultText);

                    var json = response.responseJSON;
                    if (typeof json.time != 'undefined') {
                        jQuery('#row_mageworx_alsobought_general_collect_time').find('.value .time').text(json.time);
                    }
                }
            });
        });

    });
</script>

<?php echo $block->getButtonHtml() ?>
<span class="collect-indicator" id="collect_span">
    <img class="processing" hidden="hidden" alt="Collecting" style="margin:0 5px" src="<?php echo $block->getViewFileUrl('images/process_spinner.gif') ?>"/>
    <img class="collected" hidden="hidden" alt="Collected" style="margin:-3px 5px" src="<?php echo $block->getViewFileUrl('images/rule_component_apply.gif') ?>"/>
    <span id="collect_message_span"></span>
</span>

Note: In this case, you will have to rewrite a part of the code based on your needs. Let me show you an example of how you can do that:

  • You should use the AJAX request method onCreate and onSuccess to suit your needs.
  • Besides, you can remove the <span class="collect-indicator" id="collect_span"> element.
  • We use it to show the loading (spinner) process and the result of the action.

Step 4: Create A Controller And A Router

In addition, you will need a controller (which process all further operations) and a router.

app/code/Mageplaza/HelloWorld/etc/adminhtml/routes.xml

<?xml version="1.0"?>
<!--
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Core
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */
 -->
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="mageplaza_helloworld" frontName="mageplaza_helloworld">
            <module name="Mageplaza_HelloWorld" before="Magento_Backend" />
        </route>
    </router>
</config>

app/code/Mageplaza/HelloWorld/Controller/Adminhtml/System/Config/Collect.php

<?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Core
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */
 
namespace Mageplaza\HelloWorld\Controller\Adminhtml\System\Config;
 
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Mageplaza\HelloWorld\Helper\Data;
 
class Collect extends Action
{
 
    protected $resultJsonFactory;
 
    /**
     * @var Data
     */
    protected $helper;
 
    /**
     * @param Context $context
     * @param JsonFactory $resultJsonFactory
     * @param Data $helper
     */
    public function __construct(
        Context $context,
        JsonFactory $resultJsonFactory,
        Data $helper
    )
    {
        $this->resultJsonFactory = $resultJsonFactory;
        $this->helper = $helper;
        parent::__construct($context);
    }
 
    /**
     * Collect relations data
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        try {
            $this->_getSyncSingleton()->collectRelations();
        } catch (\Exception $e) {
            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
        }
 
        $lastCollectTime = $this->helper->getLastCollectTime();
        /** @var \Magento\Framework\Controller\Result\Json $result */
        $result = $this->resultJsonFactory->create();
 
        return $result->setData(['success' => true, 'time' => $lastCollectTime]);
    }
 
    /**
     * Return product relation singleton
     *
     * @return \Mageplaza\HelloWorld\Model\Relation
     */
    protected function _getSyncSingleton()
    {
        return $this->_objectManager->get('Mageplaza\HelloWorld\Model\Relation');
    }
 
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Mageplaza_HelloWorld::config');
    }
}
?>

Conclusion

Above are the details instructions for creating an admin button in Magento 2. I hope that this article is useful for you in managing our online store effectively. As I mentioned above, this is a working example from Mageplaza extensions for Magento 2. If you have any questions related to this post, don’t hesitate to leave a comment below.

Enjoyed the tutorial? Spread it to your friends!