How to make an admin ajax call in prestashop 1.7.6 - prestashop

I'm trying to make an ajax call in Prestashop Admin:
I created a module without a config page. It just add a button in some backoffice page, I'm trying to make an ajax call to my module file without success.
Making an ajax call in frontend is working (I added an ajax.php file in my modules/mymodule/controller/front/ directory), I tried to do the same thing for admin but it's not working at all.
What I've done:
loading the js file from actionAdminControllerSetMedia is ok
adding this in the composer.json file:
"autoload": {
"psr-4": {
"MyModule\\Controller\\": "controllers/admin/"
},
"config": {
"prepend-autoloader": false
},
created the controllers/admin/ajax.php file with this code (based on this documentation code):
namespace MyModule\Controller;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
class DemoController extends FrameworkBundleAdminController
{
public $auth = false;
public $ssl = true;
public $ajax = true;
public $errors = false;
public $message;
public function __construct()
{
parent::__construct();
}
public function initContent()
{
parent::initContent();
}
public function postProcess()
{
PrestaShopLogger::addLog("MODULE CONTROLLER OK ", 1);
}
public function displayAjax()
{
$this->ajaxDie(json_encode(array('success'=> !$this->errors, 'message' => $this->message)));
}
}
Then I tried to call the ajax from different way in js but never worked (the post query return is a message from prestashop "page not found" with http 200 response.
the doc isn't very helpful and I only find old messages/ways to do (from Prestashop 1.7.5 I'd be able to create a custom Admin controller but it doesn't work), can someone explain me the steps to follow?
thanks

Assuming it is for a PS1.7+ module, using Symphony:
Declare a link in a method of your admin controller (src/Controller/Admin) e.g
$adminLink = $this->generateUrl()
and return in with:
return $this->render
In your views/js/back.js"
$.ajax({
url: adminLink,
type: 'POST',
async: false,
data: {
},
success: (data) => {
}
});
Note: check the generateUrl and render functions for the necessary arguments.

Related

Laravel 8 Route not Defined Error Caused by Auth Middleware

I am attempting to access a route defined in my routes/web.php file:
Route::get('/dashboard', [ConsoleController::class, 'dashboard'])->middleware('auth');
I am not logged in. The Authenticate.php middleware file attempts to redirect me back to the login page:
class Authenticate extends Middleware
{
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('');
}
}
}
I have also tried using return route('/'); in the Authenticate.php middleware.
My routes/web.php file has a default route which works fine if I go to the page manually:
Route::get('/', [ConsoleController::class, 'loginForm'])->middleware('guest');
However, the Authenticate.php is causing the following error:
Symfony\Component\Routing\Exception\RouteNotFoundException
Route [] not defined.
http://localhost:8888/dashboard
And it points to the following line of code:
public function route($name, $parameters = [], $absolute = true)
{
if (! is_null($route = $this->routes->getByName($name))) {
return $this->toRoute($route, $parameters, $absolute);
}
throw new RouteNotFoundException("Route [{$name}] not defined.");
}
I have found many similar posts on and off Stack Overflow, but none of those solutions have helped.
Am I naming my default route wrong? Can I not use this route in my Authenticate.php middleware? Any help would be appreciated.
Issue is, you are using route() method of Laravel, which expect route name as a parameter but you are passing actual url.
In your routes/web.php file, add name to your route as
Route::get('/dashboard', [ConsoleController::class, 'dashboard'])->middleware('auth')->name('dashboard');
Then in your Authenticate middleware file,
class Authenticate extends Middleware
{
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('dashboard');
}
}
}

How to return ajax response with error http code from PrestaShop ModuleFrontController?

I start working with PrestaShop 1.7.6 (before I worked with Symfony) and I write few custom modules to PrestaShop, but now I want send json data from my front controller module to user. Everything works fine if I send json with http code 200, but now I want send error message with proper http code (e.g 400). In Symfony I can do that by using JsonResponse (I try to do that here but it's not working as expected).I saw in presta controller are just two methods with ajax response (ajaxDie - which is deprecated and ajaxRender), but both of them doesn't takes as parameter http code response and always send 200.
if (!$product) {
$json = Tools::jsonEncode(['status' => false]);
$this->ajaxRender($json);
//return new JsonResponse($json, Response::HTTP_BAD_REQUEST);// doesn't send proper code
}
Can anyone tell me how to send error code from module front controller which extends ModuleFrontController?? Now only possible to me action is send error message with http code 200 (but I think it's bad idea to send error with that code). Thanks a lot for any help.
The proper way to send and receive data using AJAX is displayed below.
More information can be found at Prestashop Docs
Ajax post
$.ajax({
type: 'POST',
dataType : 'json',
url: 'linktoyourfile.php',
data: { action: 'getMyrequest' },
success: function(data) {
alert(data.result);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error: ' + textStatus + ' ' + errorThrown);
}
});
Module Front Controler
class TestModuleFrontController extends ModuleFrontController
{
public function init()
{
parent::init();
}
public function displayAjaxGetMyrequest()
{
// ERROR HANDELING
if ($this->errors) {
die(Tools::jsonEncode(array('hasError' => true, 'errors' => $this->errors)));
} else {
echo Tools::json_encode(array('result' => 'test result'));
}
}
}

Cannot get json data with ajax in Razor Pages [duplicate]

This question already has answers here:
Example AJAX call back to an ASP.NET Core Razor Page
(8 answers)
Closed 5 years ago.
i am trying to get some data from Razor Pages in ASP.NET Core 2.0.
But the problem is that it does not returns any data.
I also tried debugging it, it does not fire that method (OnGetProducts) at all.
The model Index.cshtml.cs:
private IProductRepository _productRepository;
public IndexModel(IProductRepository repository)
{
_productRepository = repository;
}
public void OnGet()
{
}
public IActionResult OnGetProducts(int page)
{
var model = _productRepository.GetProducts().Skip(page * 10).Take(10);
return new JsonResult(model);
}
the razor page Index.cshtml
<div id="products">
</div>
#section scripts{
<script>
$(function () {
getProducts(0);
});
var isInitialized = false;
function getProducts(page) {
$.ajax({
type: 'GET',
url: "Products",
contentType: "application/json",
dataType: "json",
data: {
handler: 'Products',
page: page
},
success: function (datas) {
console.log(datas);
}
});
}
</script>
}
p.s. this page in in folder Pages/Products/Index.cshtml(.cs)
I usually use razor functions to generate URLs instead of hard coding them in js. If your action is not even being triggered, assuming that you are not accidentally in release mode, it is because the URL doesn't point to the right location. First of all set js variables in razor something like this:
var productsURL = #Url.Context("~/products");
Also run yourdomain/products in your browser and if you get a 404.
Alternatively I use this function to directly use c# objects in js:
public static IHtmlContent ToJS(this IHtmlHelper htmlHelper, object obj)
=> htmlHelper.Raw(JsonConvert.SerializeObject(obj));
With this function created in a static class, you can also create a js object directly something like this:
<script>
var products = #Html.ToJS(repository.GetProducts().Skip(page * 10).Take(10));
</script>
Of course this will only create the object in page load, if you want it to change after page load, you can consider creating a partial view via ajax. Also note that the second alternative will be slower than the first for ajax.

Can I set authorization headers with RequireJS?

We want to have 2 sets of resources for our AngularJS app (public/private) which uses RequireJS for dependency management. Basically everything on the login page would be public and once logged in, another angularjs app would be loaded (new requirejs config) that would load resources that require authentication to access.
Is there a way to configure requirejs to set an authorization header when loading resources?
It depends on what you mean by "resources" and how your server is configured. But in general - yes, since you are using AngularJS you can use the $httpProvider to inject an interceptor service.
For example, in a service:
var dependencies = ['$rootScope', 'userService'];
var service = function ($rootScope, userService) {
return {
request: function(config) {
var currentUser = userService.getCurrentUser();
var access_token = currentUser ? currentUser.access_token : null;
if(access_token) {
config.headers.authorization = access_token;
}
return config;
},
responseError: function (response) {
if(response.status === 401) {
$rootScope.$broadcast('unauthorized');
}
return response;
}
};
};
module.factory(name, dependencies.concat(service));
Then, after you configure your routes, you can use:
$httpProvider.interceptors.push( 'someService');
You can find some more information on interceptors here: https://docs.angularjs.org/api/ng/service/$http#interceptors
UPDATE
You might be able to use the text plugin to try and receive it, but I don't see the point in protecting client side code. Plus, if you want to use optimization the resources will just come in one file anyway...
config: {
text: {
onXhr: function (xhr, url) {
xhr.setRequestHeader('Authorization','Basic ' + token);
}
}
}
Refer to: custom-xhr-hooks
Another UPDATE
You could also use urlArgs (mainly used for cache invalidation) without using the text plugin:
require.config({
urlArgs: 'token='+token,
...
)}

Call Ajax Play FrameWork

I have a problem with ajax, play framework 2.1.1:
My Play Project
routes:
POST /sample/testapi controllers.Application.testapi()
GET /sample/ajax controllers.Application.ajax()
Application.java
public static Result testapi() {
DynamicForm dynamicForm = DynamicForm.form().bindFromRequest();
String data= dynamicForm.get("data");
Logger.debug(data);
return ok("<user no='1'><id>1</id><name>Peter</name></user>");
}
public static Result ajax() {
return ok(ajax.render());
}
When I call action "testapi" from ajax.scala.html through ajax
My ajax code
$.ajax({
url : "http:// localhost:3333/sample/testapi",
type: 'POST',
data: {data: "test"},
dataType: "text",
success : function(result) {
alert(result);
},
error : function(request,error) {
alert(error);
}
});
It working fine.
And I have a html file and I call to play project through ajax.
The action had been called, but not return result and show alert "error".
Please help me. Thanks.
I added "response().setHeader("Access-Control-Allow-Origin", "*");" to my action.
public static Result testapi() {
response().setHeader("Access-Control-Allow-Origin", "*");
DynamicForm dynamicForm = DynamicForm.form().bindFromRequest();
String data= dynamicForm.get("data");
Logger.debug(data);
return ok("<user no='1'><id>1</id><name>Peter</name></user>");
}
"response().setHeader("Access-Control-Allow-Origin", "*");" allow other domain call it.