Jump to content

AJAX Request to Custom Admin Module Controller


Recommended Posts

Hi Guys,

I am using Prestashop 1.7 and I created custom admin module controller class. What is the proper way to call a method inside my controller using AJAX request?

For example:

class AdminFooBarController extends ModuleAdminController
{
    public function ajaxProcessGetBar()
    {
		return 'foo';
    }
}

 

and in the backoffice template I have:

$.ajax({
  type: 'POST',
  cache: false,
  dataType: 'json',
  url: 'ajax-tab.php', // not sure about this part
  data: {
    ajax: true,
    controller: 'AdminFooBar',
    action: 'GetBar',
    token: token
  },
  success: function (data) {
    // something magical 
  }
});

I can't seem to get it work.

Thanks

  • Like 1
Link to comment
Share on other sites

Hello:

Your controller code seems to be right. Try this with the JS:

$.ajax({
  type: 'POST',
  cache: false,
  dataType: 'json',
  url: 'index.php', // fix this
  data: {
    ajax: true,
    controller: 'AdminFooBar',
    action: 'getBar', // prestashop already set camel case before execute method
    token: token
  },
  success: function (data) {
    // something magical 
  }
});

Regards

  • Thanks 1
Link to comment
Share on other sites

try this,

$.ajax({
            type: 'POST',
            dataType: 'json',
            url: 'ajax-tab.php',
            data: {
                ajax: true,
                controller: 'AdminFooBar',
                action: 'youraction', // small letter case
                var1: your_variable, // if you want to send some var
                token: $('#your_DOM_identifier').attr('data-token'), // your token previously set in your DOM element
            },
        })
            .done(function (data) {
}

 

Link to comment
Share on other sites

Thanks for Your responses. Unfortunately both of propose solution didn't work. 

The payload looks as follows:

  • request url is {my_domain}/admin/index.php
  • form data: ajax=true&controller=AdminFooBar&action=getbar&token={token}

Although the response results in 200, no data is return back. Only security template "INVALID SECURITY TOKEN". 

Any ideas?

Link to comment
Share on other sites

  • 3 months later...
  • 2 months later...

Believe it or not, i think the only error was ajax: true instead of ajax: 1.

This worked FINALLY for me:

	var postdata = {
		ajax: 1,
		controller: 'AdminFooBar',
		action: 'getBar',
		token: token
	  };
	$.ajax({
	  type: 'POST',
	  url: 'index.php',
	  data: postdata,
	  success: function(r){
		//magic
	  }
	});

 

Link to comment
Share on other sites

  • 4 months later...
On 2/15/2019 at 2:22 PM, fanie said:

How do you return your data from the php function ?

Instead of 


return $result;

you can try


 die(Tools::JsonEncode($result));

 

That's really bad solution.

In new PrestaShop you should use JsonResponse in your Symfony type controller.
 

use Symfony\Component\HttpFoundation\JsonResponse;

return new JsonResponse([
            "1" => [
                "ID" => "123-265",
                "ID eshop"=> "System Architect",
                "Kategorie"=> "$320,800",
                "Počet položek"=> "2011/04/25",
                "Kategorie"=> "Edinburgh",
                "Podkategorie_1"=> "5421",
                "Podkategorie_2"=> "5421",
                "Podkategorie_3"=> "5421",
                "Počet položek eshop"=> "5421"
                ]
            ]
        );

 

  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

I just ran into a massive problem that took me a long time to figure out. Documenting this here in case it'll be helpful for someone in the future:

 

My ajax calls had been running smoothly so far. But suddenly they stopped working.

 

Turns out there are 2 types of ajax methods:

 

public function ajaxProcessGetBar(){
	// this will be called in combination with postProcess()
	// on your ajax call, if you have submitted $_POST['action'] = 'getBar';  
	// then this will be called.
}

public function displayAjaxGetbar(){
	//this will be called even without the post process, as long as $_POST['ajax'] = 1;
	// on your ajax call, if you have submitted $_POST['action'] = 'getBar'; 
	// notice that you have to change the function name to all lower case.
}

 

So, here's what's important to consider:

class AdminFooBarController extends ModuleAdminController
{
    public function postProcess()
    {
        return parent::postProcess(); // IF YOU DON'T DO THIS FOR ANY REASON
    }

	public function ajaxProcessGetBar()
    {
		return 'foo'; //THIS WON'T BE FUNCTIONING PROPERLY
    }
}

 

Also a nifty little function I found while debugging this:

 

abstract class ControllerCore
{
     /**
     * Dies and echoes output value
     *
     * @param string|null $value
     * @param string|null $controller
     * @param string|null $method
     */
    protected function ajaxDie($value = null, $controller = null, $method = null)
    {
        if ($controller === null) {
            $controller = get_class($this);
        }

        if ($method === null) {
            $bt = debug_backtrace();
            $method = $bt[1]['function'];
        }

        Hook::exec('actionBeforeAjaxDie', array('controller' => $controller, 'method' => $method, 'value' => $value));
        Hook::exec('actionBeforeAjaxDie'.$controller.$method, array('value' => $value));

        die($value);
    }

}

So this function/method ajaxDie is located in the Controller (myshop\classes\controller\Controller.php)

You should be able to use it in your module controller to echo ajax values and exit the script, since they all inherit each other

(AdminFooBarController extends ModuleAdminController extends AdminControllerCore extends Controller)

So, what @haunter said... simply using die(); isn't necessary/or a "good" solution, because  there's a specific function made for that: ajaxDie(); and it will even execute the hook actionBeforeAjaxDie for you.

 

Hope this helps someone! 🙂

 

  • Like 2
Link to comment
Share on other sites

  • 6 months later...
On 10/23/2018 at 4:17 AM, Deadpool said:

Thanks for Your responses. Unfortunately both of propose solution didn't work. 

The payload looks as follows:

  • request url is {my_domain}/admin/index.php
  • form data: ajax=true&controller=AdminFooBar&action=getbar&token={token}

Although the response results in 200, no data is return back. Only security template "INVALID SECURITY TOKEN". 

Any ideas?

 This is very old post, but i have the solution, hope this help someone

 

You'r solution is correct, to fix token issue, get token value like this:

$token_foo = Tools::getAdminTokenLite('AdminFooBar');

 

Link to comment
Share on other sites

  • 3 months later...

I added the full details here

First you have to add Ajax link in hook or somewhere with

// Create a link with the path

$adminajax_link = $this->context->link->getAdminLink('YourAdminModule');


//define js value to use in ajax url
Media::addJsDef(array(

	"adminajax_link" => $adminajax_link

));

And in your admin Module code looks like

<?php

class YourAdminModuleController extends ModuleAdminController
{

    public function ajaxProcessYourActionName()
    {
		echo json_encode('foo');//something you want to return
        exit;
    }

}

and in your JS would be

$.ajax({
            type: 'POST',
            cache: false,
            dataType: 'json',
            url: adminajax_link, 
            data: {
                ajax: true,
                action: 'youractionname'//lowercase with action name
            },
            success : function (data) {
                console.log(data);
            },
            error : function (data){
                console.log(data);
            }
            
        });

 

  • Thanks 1
Link to comment
Share on other sites

  • 2 months later...

Good day - I can not for the life of me get an ajax call to work.

PrestaShop: 1.7.6.5
Module: CustomModule

Ajax URL:
https://domain/module/CustomModule/CustomModuleOrderManagerController?action=productStockIssue&id_product=###&id_order=###&ajax=true
(Context::getContext()->link->getModuleLink( 'CustomModule', 'CustomModuleOrderManagerController' ))
OR
https://domain/admin/index.php?controller=CustomModuleOrderManagerController&token=######?action=productStockIssue&id_product=###&id_order=###&ajax=true
(Context::getContext()->link->getAdminLink( 'CustomModuleOrderManagerController' ))

$.ajax( {
			type    : "GET",
			url     : link,
			data    : {
				ajax   : true,
				action : 'productStockIssue'
			},
			async   : true,
			cache   : false,
			beforeSend: function() {
				
			},
			complete: function() {
				
			},
			success: function( data ) {
				console.log( data );
			},
			error: function( XMLHttpRequest, textStatus, errorThrown ) {
				console.log( XMLHttpRequest );
				alert( XMLHttpRequest.responseText );
			}
		} );
class CustomModuleOrderManagerController extends ModuleAdminController {
	public function displayAjaxProductStockIssue() {
		$this->ajaxDie( Tools::jsonEncode( ['error' => 'This is a test.'] ) );
	}

	public function processProductStockIssue() {
		$this->ajaxDie( Tools::jsonEncode( ['error' => 'This is a test 2.'] ) );
	}

	public function ajaxProcessProductStockIssue() {
		$this->ajaxDie( Tools::jsonEncode( ['error' => 'This is a test 3.'] ) );
	}
}

Am I missing something? It just responds with "404 not found" with everything that I've tried.

Edited by Estian (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...
On 10/21/2020 at 3:43 PM, Estian said:

Turns out I had to register a "tab" (the controller name) for the controller in "installTab()" during module installation.

It shouldn't be necessary as in Prestashop >1.7.5 you can load a custom admin controller without registering a Tab.

But... the doc is pretty confusing, I failed to do it, does anyone know how to register an admin controller and use it in ajax from backoffice?

 

Edited by Cryonos80 (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...

Hi There, 

There is a plenty of way to integrate ajax functionality to an admin module controller. 

First you need to bind an ajax function on click of that  button. You also need to send the module admin controller link to the js file. You can send the file via custom script tag in your helper form.

<?php 
$link = new Link(); 
$urladmin = $link->getAdminLink( 'YourControllerName' ); 
?> 
<script type="text/javascript"> 
  var priceExpiryDate = "{$urladmin}"; 
</script>

Then you can use ajax to fire function on the server. 

$.ajax({ 
type: 'POST', 
cache: false, 
dataType: 'json', 
url: adminajax_link, 
data: { 
  ajax: true, 
  action: 'yourActionName'//lowercase with action name 
}, 
  success : function (data) { 
  console.log(data); 
  }, 
  error : function (data){ 
  console.log(data); 
  } 
});

Then do your php on code on the function e.g. that is your actionname in your admin controller class.

public function ajaxProcessYourActionName() { 
	echo json_encode('foo');//something you want to return 
	exit; 
}

Please mind the camel case of the name.

Boom It is done.

Link to comment
Share on other sites

On 11/6/2020 at 6:10 PM, Cryonos80 said:

It shouldn't be necessary as in Prestashop >1.7.5 you can load a custom admin controller without registering a Tab.

But... the doc is pretty confusing, I failed to do it, does anyone know how to register an admin controller and use it in ajax from backoffice?

 

This has been some time ago but as far as I remember I just could not get it to work... and then I registered it as a tab and as ClassyDevs said, "Boom!" it worked haha.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...