How to send ADMIN AJAX request?
-
13-04-2021 - |
Question
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>
Solution
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
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
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>
OTHER TIPS
You need to include jquery first. Use this to code to do it:
require([
"jquery"
], function ($) {
//your code to send ajax request here
$.ajax({
showLoader: true,
url: "admin/PostaPlus/PostaPlusShipping/HSCodes",
data: param,
type: "POST",
dataType: 'json'
}).done(function (data) {
alert(data); console.log(data);
});
});
I don't know why but the admin Ajax requests only pass in GET
anyway for me.
I had the same problem as you and I solved my problem with passing the request in GET
and it works properly.
Another very important thing is to disable the admin secret key in URL otherwise you can't access to your controller.
You can remove it in : Stores > Configuration > Advanced > Admin > security > Add Secret Key to URLs > No
.
Also You should use dataType: 'json'
to not return the html code response.
Admin AJAX exemple :
adminhtml/templates/file.phtml
require(['jquery', 'jquery/ui'], function($){
var ajaxRequest;
ajaxRequest = jQuery.ajax({
url: "<?php echo $this->getUrl('adminrouter/folder/index'); ?>",
type: 'GET',
data: {id : 1}, //exemple
dataType: 'json',
beforeSend: function () {
jQuery('#loader').show();
}
});
//Show successfully for submit message
ajaxRequest.done(function (response, textStatus, jqXHR) {
jQuery("#ajaxResponse").html(response);
jQuery('#loader').hide();
});
//On failure of request this function will be called
ajaxRequest.fail(function () {
//show error
jQuery("#ajaxResponse").html('Oops, An error occured, please try again later!');
jQuery('#loader').hide();
});
});
app/code/{Vendor}/{Module}/Controller/Adminhtml/Folder/Index.php
<?php
namespace Vendor\Module\Controller\Adminhtml\Folder;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Backend\App\Action;
use Magento\Framework\Controller\ResultFactory;
class Index extends Action
{
protected $logger;
public function __construct(
\Magento\Backend\App\Action\Context $context
,\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Psr\Log\LoggerInterface $logger
) {
parent::__construct($context);
$this->resultJsonFactory = $resultJsonFactory;
$this->logger = $logger;
}
/**
* @return \Magento\Framework\Controller\Result\Json
*/
public function execute() {
//get AjaxQuery params, GET method !
$params = $this->getRequest()->getParams();
$this->logger->info($params); // For debug
\Zend_Debug::dump($params); // For debug
//Send response to Ajax query
$data = 200;
$result = $this->resultJsonFactory->create();
return $result->setData($data);
}
}
I hope it helps you or someone else.
Add your controller file at
PostaPlus\PostaPlusShipping\Controller\Adminhtml\PostaPlusShipping\HSCodes.php
Now your ajax url is routname\controller\action
PostaPlus\PostaPlusShipping\HSCodes
add ajax code
var param = 'ajax=1';
$.ajax({
showLoader: true,
url: YOUR_URL_HERE,
data: param,
type: "POST",
dataType: 'json'
}).done(function (data) {
console.log(data);
});
Change controller execute method
public function execute()
{
return $this->resultJsonFactory->create()->setData(['a' => 'b']);
}