3

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>
PЯINCƎ
11.8k3 gold badges27 silver badges85 bronze badges
asked Feb 8, 2017 at 7:59
2
  • Any reason why you have admin_hs_codes instead of admin for your router id? Try changing it and clearing cache. Commented Mar 10, 2018 at 23:27
  • magento.stackexchange.com/a/231316/100241 This helped me and save the time Commented Sep 9, 2022 at 15:18

5 Answers 5

2

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>
answered Apr 15, 2020 at 19:25
3

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.

answered Jun 25, 2018 at 22:21
1
  • 1
    this ajax "GET" call instead of "POST" helped me out i also dont know why but this helps Commented Apr 7, 2020 at 9:56
2

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); 
 });
});
answered Feb 8, 2017 at 8:30
11
  • I did added like that and functions are working fine. Only AJAX return has the problem, <script> require([ "jquery", "jquery/ui" ], function($){ hscodes= { ............... ............... }); </script> Commented Feb 8, 2017 at 8:34
  • Try echoing the value in controller action and use .success() function instead of .done() in your ajax call Commented Feb 8, 2017 at 8:40
  • Tested as below but still same. changed in controller, public function execute() { //return $this->resultJsonFactory->create()->setData(['a' => 'b']); echo 'test string'; changed in JS, .success(function (data){ alert(data); console.log(data); }) But same results Commented Feb 8, 2017 at 8:49
  • Do you get any error ?? Try to use firebug in Firefox it will show you error Commented Feb 8, 2017 at 8:50
  • No errors. I get output as entire current page as html codes. I check in Chrome developer tool only. Commented Feb 8, 2017 at 8:54
0

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']);
 }
answered Feb 8, 2017 at 9:02
3
  • I created PostaPlusShipping folder and moved HSCodes class file in it. I tried with same ajax URL but still I get html codes. I think something to do with my routes.xml file? Otherwise how could it returns html values even if I dont specify a URL? any suggestions on how to resolve this routes.xml? Commented Feb 8, 2017 at 9:22
  • update answer please check it Commented Feb 8, 2017 at 9:30
  • After doing all these changes I'm getting html response of admin home page. My request is redirected to home page from server and getting it as html codes Commented Feb 8, 2017 at 9:58
0

I think it's too late but I found the solution

You can simple override admin resource const in your controller. Add to your controller const ADMIN_RESOURCE = 'Magento_Widget::widget_instance'; or extend Magento\CatalogWidget\Controller\Adminhtml\Product\Widget.

No need to disable admin secret key. And Post method will work.

Solution found in Magento_PageBuilder module. Class Magento\PageBuilder\Controller\Adminhtml\Form\Element\ProductTotals.

plus you can pass url in xml enter image description here

and your js file enter image description here

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.