Send ADMIN AJAX Request in Magento 2 – How to Guide

adminadmin-controllerajaxmagento2

I need to retrieve some information from my custom admin controller using AJAX.
But when AJAX is used I get current page's entire HTML !

I simply want to get some JSON data from my custom controller. That I will implement later on.

I'm calling my custom controller from a block in this

URL .../admin/admin/order_shipment/new/order_id/...

Here is my ajax call

 var param = 'form_key='+window.FORM_KEY;
         $.ajax({
                 showLoader: true,
                 url: "admin/PostaPlus/PostaPlusShipping/HSCodes",
                 data: param,
                 type: "POST",
                // dataType: 'json'
                }).done(function (data) {                        
                    alert(data);                        
                    console.log(data);
                 });

Here is my custom controller codes,

<?php
 namespace PostaPlus\PostaPlusShipping\Controller\Adminhtml;
 use Magento\Backend\App\Action;

 class HSCodes extends \Magento\Backend\App\Action
{

   protected $resultJsonFactory;

   public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory 
        )
  {
    parent::__construct($context);
    $this->resultFactory = $resultJsonFactory;
  }

  public function execute()
  {
    //return $this->resultJsonFactory->create()->setData(['a' => 'b']);
    return 'test string';
  }

  public function indexAction(){

    //echo 'test string';
  }
}

Here is my route file,

<?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="admin_hs_codes">
      <route id="PostaPlus" frontName="PostaPlus">
        <module name="PostaPlus_PostaPlusShipping"/>
      </route>
    </router>
 </config>

Best Answer

I had tried all of the above methods but non of them are working or incomplete so I had decided to answer it in details: Following will be module minimal diagram

enter image description here

1)

<?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="admin">
        <route frontName="groupproduct" id="groupproduct">
            <module before="Magento_Backend" name="Textmimedia_Partpicker"/>
        </route>
    </router>
</config>

2)

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Levosoft_Partpicker" setup_version="1.0.0"/>
</config>

3) Need to declare admin router

    <?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="admin">
        <route frontName="groupproduct" id="groupproduct">
            <module before="Magento_Backend" name="Levosoft_Partpicker"/>
        </route>
    </router>
</config>

4)

<?php


namespace Levosoft\Partpicker\Controller\Adminhtml\Imagetag;

/**
 * Class Save
 *
 * @package Levosoft\Partpicker\Controller\Adminhtml\Imagetag
 */
class Save extends \Magento\Backend\App\Action
{

    protected $resultPageFactory;
    protected $jsonHelper;

    /**
     * Constructor
     *
     * @param \Magento\Backend\App\Action\Context  $context
     * @param \Magento\Framework\Json\Helper\Data $jsonHelper
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->resultPageFactory = $resultPageFactory;
        $this->jsonHelper = $jsonHelper;
        $this->logger = $logger;
        parent::__construct($context);
    }

    /**
     * Execute view action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            return $this->jsonResponse('your response');
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            return $this->jsonResponse($e->getMessage());
        } catch (\Exception $e) {
            $this->logger->critical($e);
            return $this->jsonResponse($e->getMessage());
        }
    }

    /**
     * Create json response
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function jsonResponse($response = '')
    {
        return $this->getResponse()->representJson(
            $this->jsonHelper->jsonEncode($response)
        );
    }
}

Now Client Part which is actually bit tricky I am calling it in js file like somefilename.js

var ajaxRequest;
                var saveUrl = gpImageTagSaveUrl+'?isAjax=true'; //module url declared globally in module;

                ajaxRequest = $.ajax({
                    showLoader: true,
                    url: saveUrl,
                    data: {form_key: window.FORM_KEY},
                    type: 'POST',
                    dataType: 'json',
                    beforeSend: function () {
                        $('#loader').show();
                    }
                });
                //Show successfully for submit message
                ajaxRequest.done(function (response, textStatus, jqXHR) {
                    $("#ajaxResponse").html(response);
                    $('#loader').hide();
                });

                //On failure of request this function will be called
                ajaxRequest.fail(function () {
                    //show error
                    $("#ajaxResponse").html('Oops, An error occured, please' +
                        ' try again later!');
                    $('#loader').hide();
                });

gpImageTagSaveUrl is globel variable which will hold your modules url you can declare it in some js file like following

enter image description here

I had used catalog_product_edit.xml file because I want it at product edit location you can add it in your required file or in default.xml if required on all.

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="js">
            <block class="Magento\Backend\Block\Template" template="Levosoft_Partpicker::js.phtml"
                   name="custom_js_backend"/>
        </referenceContainer>
    </body>
</page>

Now in js.phtml declare action url like following:

<script>
    require([
        "prototype"
    ], function () {
        window.gpImageTagSaveUrl = '<?= /** @noEscape */ $block->getUrl('groupproduct/imagetag/save')?>';
    });
</script>
Related Topic