Call a prestashop module with ajax - ajax

I have a PrestaShop module called 'MyMenu' and I want call this menu with an AJAX call.
My module is displayed in the hookFooter() method:
public function hookFooter()
{
$display = $this->display(__FILE__, 'megamenu.tpl', $smartyCacheId);
Tools::restoreCacheSettings();
return $display;
}
I want display with this script:
<div class="load_menu"></div>
<script>
$(document).ready(function (e) {
$.ajax({
method: "POST",
url: "../modules/MyMenu.php",
data: {},
success: function (data) {
$('.load_menu').html(data);
}
})
});
</script>

The best way is to do it via a front controller linked to your module.
You can call the url like this :
$link->getModuleLink('modulename','controller', $parameters);
// Parameters is an optionnal array, it can be empty
And for the controller, place a file like this ./modules/modulename/controllers/front/ajax.php with this kind of content :
class ModuleNameAjaxModuleFrontController extends ModuleFrontController
{
public function initContent()
{
$response = array('status' => false);
require_once _PS_MODULE_DIR_.'modulename/modulename.php';
$module = new ModuleName;
if (Tools::isSubmit('action')) {
$context = Context::getContext();
$cart = $context->cart;
switch (Tools::getValue('action')) {
case 'actionname':
$response = array('status' => true);
break;
default:
break;
}
}
// Classic json response
$json = Tools::jsonEncode($response);
$this->ajaxDie($json);
// For displaying like any other use this method to assign and display your template placed in modules/modulename/views/template/front/...
// $this->context->smarty->assign(array('var1'=>'value1'));
// $this->setTemplate('template.tpl');
// For sending a template in ajax use this method
// $this->context->smarty->fetch('template.tpl');
}
}

If you don't want to pass the url by the module, the js snippet should be like this.
$(document).ready(function(){
$.ajax({
type: "POST",
headers: { "cache-control": "no-cache" },
url : baseDir + 'modules/yourmodulename/yourfile.php',
data: {
token : token
},
success : function(data){
$('.load-menu').html(data)
}
});
});
Where yourmodulename is the name of your module and yourfile.php is the code where you retrieve the menu.
Don't forget to add to your data the token, it's to prevent a CSFR attack, obviously you have to check the token in your server side script as well.

In a new file at the module root, you can create a file "ajax.php"
require_once(MODULE_DIR.'MyMenu/mymenu.php');
if(Tools::getValue('token') !=
$mymenu = Module::getInstanceByName('mymenu');
$menu = $mymenu->hookFooter();
die($menu);
In your js, at the root of your module
<script>
$(document).ready(function (e) {
$.ajax({
method: "POST",
url: "./ajax.php",
data: {},
success: function (data) {
$('.load_menu').html(data);
}
})
});
</script>

Related

CSRF token mismatch while uploading image using ajax in CakePHP 3.6

I have tried
class UsersController extends AppController
{
public function beforeFilter(Event $event)
{
$this->getEventManager()->off($this->Csrf);
}
public function ajaxEdit($id = null)
{
$this->autoRender = false;
debug($id);
debug($this->request->getData());
}
And I am using ajax code
$(document).ready(function(){
$('#user-profile').change(function(){
$('.loader-body').show();
var form = $('#user-profile-image')[0];
var formData = new FormData(form);
var tutorial_id = $('#user-file-id').val();
$.ajax({
url :"/users/ajax-edit/"+tutorial_id,
method:"POST",
data:formData,
contentType:false,
cache: false,
processData:false,
success:function(data){
let parseData = $.parseJSON(data);
if (parseData.status === true) {
location.reload();
var value = parseData.url;
console.log(value);
} else {
alert(parseData.message);
}
}
});
});
});
I have followed help from these links
CakePHP ajax CSRF token mismatch
2 https://book.cakephp.org/3.0/en/controllers/components/csrf.html
Getting CSRF token mismatch (see attached image)
https://i.stack.imgur.com/FsVZu.png
First of all if your are using POST method in your ajax call then you should send tutorial_id as data instead of sending it in the url.
You can resolve this by sending you CSRF token through a special X-CSRF-Token header in your ajax call.
https://book.cakephp.org/3.0/en/controllers/components/csrf.html
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('[name="_csrfToken"]').val());
},
OR
You can disable CSRF component[Not recommended by the Cakephp] for your ajax action like:
public function beforeFilter(Event $event) {
if (in_array($this->request->action, ['ajaxEdit'])) {
$this->eventManager()->off($this->Csrf);
}
}

Ajax call with Zend Framework 2

I am trying to call an action in a controller via an ajax request and it works but it also loads the layout twice and I am getting this notice: "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/." The url where the ajax request is being sent at is /admin/errors.
Here is the code:
<script type="text/javascript">
$("input").on("click", function() {
$.ajax({
type: "POST",
url: "<?php echo $this->url('admin', array('action' => 'geterror')); ?>",
data: { error_type: $("input:checked").val() },
success: function(data) {
$('#view-errors').html(data + "<br>");
}
});
});
</script>
and the code in the action:
public function geterrorAction()
{
if (!$user = $this->identity()) {
return $this->redirect()->toUrl('/login/log');
}
$user = $this->identity();
$layout = $this->layout();
$layout->setTerminal(true);
echo ErrorView::viewErrors($_POST['error_type']);
}
Here is a image to better help explain.
Appreciate any help!
Add a blank layout file inside layout directory.
use $this->layout('layout/blank'); inside the action of the controller. This will set a blank layout.
public function geterrorAction()
{
$this->layout('layout/blank');
// .... other codes
}
try setting the terminal true on the view model
public function geterrorAction()
{
if (!$user = $this->identity()) {
return $this->redirect()->toUrl('/login/log');
}
$user = $this->identity();
$layout = $this->layout();
echo ErrorView::viewErrors($_POST['error_type']);
$view = new ViewModel();
$view->setTerminal(true);
return $view;
}

Render partial view with AJAX-call to MVC-action

I have this AJAX in my code:
$(".dogname").click(function () {
var id = $(this).attr("data-id");
alert(id);
$.ajax({
url: '/Home/GetSingleDog',
dataType: 'html',
data: {
dogid: id,
},
success: function (data) {
$('#hidden').html(data);
}
});
});
The alert gets triggered with the correct value but the AJAX-call does not start(the method does not get called).
Here is the method that im trying to hit:
public ActionResult GetSingleDog(int dogid)
{
var model = _ef.SingleDog(dogid);
if (Request.IsAjaxRequest())
{
return PartialView("_dogpartial", model);
}
else
{
return null;
}
}
Can someone see what i am missing? Thanks!
do you know what error does this ajax call throws?
Use fiddler or some other tool to verify response from the server.
try modifying your ajax call as following
$.ajax({
url: '/Home/GetSingleDog',
dataType: 'string',
data: {
dogid: id,
},
success: function (data) {
$('#hidden').html(data);
}
error: function(x,h,r)
{
//Verify error
}
});
Also try
$.get("Home/GetSingleDog",{dogid : id},function(data){
$('#hidden').html(data);
});
Make sure, URL is correct and parameter dogid(case sensitive) is same as in controller's action method

Extjs 4 downloading a file through ajax call

The problem is very simple: i have to download a file when i submit a form, it's an ajax call when the form is submitted which lets me build a file with the data taken from the form, server side, and then send it as a link to an alert. The fact is that my boss want the file to be downloaded directly and not through a link in an alert. So i had to make sure that the file is available server side through tornado(web):
self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=clients_counter.zip')
with open("static/clients_counter.zip", 'r') as f:
while True:
data = f.read()
if not data:
break
self.write(data)
self.finish()
The server side code seems to work fine, but the client side (extjs4.1) is really a nightmare. This is how my ajax call looks like now, and it doesn't work:
Ext.Ajax.request({
method : "GET",
url : 'http://whatever.com/count?client='+client+'&start='+start+'&end='+end,
timeout : 30000,
success :
function (response) {
//Ext.Msg.alert(response.responseText);
desktop.getWindow('count-win').doClose();
return response;
}//handler,
failure :
function(response) {
alert("Wrong request");
}});
After reading on various sources from Ext JS forum and here in stackoverflow, below is the approach I've chosen (using Ext JS version 4.2.1):
downloadFile: function(config){
config = config || {};
var url = config.url,
method = config.method || 'POST',// Either GET or POST. Default is POST.
params = config.params || {};
// Create form panel. It contains a basic form that we need for the file download.
var form = Ext.create('Ext.form.Panel', {
standardSubmit: true,
url: url,
method: method
});
// Call the submit to begin the file download.
form.submit({
target: '_blank', // Avoids leaving the page.
params: params
});
// Clean-up the form after 100 milliseconds.
// Once the submit is called, the browser does not care anymore with the form object.
Ext.defer(function(){
form.close();
}, 100);
}
I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:
Make a standard sumbit instead of Ajax.
var form = Ext.create('Ext.form.Panel', { // this wolud be your form
standardSubmit: true, // this is the important part
url: '../ObtenerArchivoAdjuntoServlet'
});
form.submit({
params: {
nombreArchivo: nombreArchivo
}
});
After this you would be able return the desired file.
After extracting/reading many posts, I managed to get this simple method to work..
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
standardSubmit: true,
url: 'URL'
}).submit({params: {'PARAM1': param1, 'PARAM2': param2}});
I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:
window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)
This will open a new tab and start the download from there.
The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.
use an iframe like this:
/**
* prints the file
*/
printReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
Ext.DomHelper.append(Ext.getBody(), {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: url
});
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
Copied the answer from extjs forum
Option:2
If you want to open the file in new tab
/**
* open file in tab
*/
openReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
var win = window.open('', '_blank');
win.location = url;
win.focus();
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.
FileDownload.downloadFile = function(arguments) {
var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];
var body = Ext.getBody();
var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});
var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});
if (params) {
for (var paramName in params) {
form.createChild({
tag:'input',
cls:'x-hidden',
id:'hiddenform-'+paramName,
type: 'text',
text: params[paramName],
target:'iframe',
value: params[paramName],
name: paramName
});
}
}
form.dom.submit();
FileDownload.isFinished(successCallback,failureCallback);
};
FileDownload.isFinished = function(successCallback,failureCallback) {
//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
//Remove cookie call success callback
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
successCallback();
return;
}
//Check for error / IF any error happens then frame will load with content
try {
if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
failureCallback();
//Cleanup
Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = "";
return;
}
}
catch (e) {
console.log(e);
}
console.log('polling..');
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);
};
Usage :
FileDownload.downloadFile({
url : url,
params : params,
success : function(){
//Success call back here
},
failure : function(){
//Failure callbak here
}
});
In the http response you need to add a cookie nammed fileDownload = true
I just had to ad to the success function of the ajax request:
window.open('urltothefile.ext')

Joomla 2.5 Ajax component not working

I've been trying for ages to get Json working in Joomla and I just can't do it. I think I've tried every combination of URL etc so any help would be great:
this is for the admin side structure looks like
admin
-controllers
--orderitem.php
-views
--orderitem
---tmpl
----orderitem.php
-controller.php
function updateNow(newrefresh) {
var dataJSON = JSON.encode (newrefresh);
var request = new Request.JSON({
method: 'post',
url: 'index.php?option=com_customersitedetails&view=orderitem&task=refreshscreen&format=raw',
data: {
json: dataJSON
},
onComplete: function(jsonObj) {
alert("Your form has been successfully submitted ");
}
}).send();
};
Although runs the alert box it doesn't retun JSON just
View not found [name, type, prefix]: orderitem, raw, customersitedetailsView
Any ideas where I can start? thanks
You're missing views/orderitem/view.raw.php containing a CustomersitedetailsViewOrderitem class.
views/orderitem/view.raw.php
class CustomersitedetailsViewOrderitem extends JViewLegacy
{
public function display($tpl = null)
{
$response = 'Your magic response here';
echo $response;
JFactory::getApplication()->close();
}
}
You can look here for proper ajax call in joomla
How to Write PHP in AJAX
inside your controllers you should have a file "mycall.json.php" this file will process and return a json format of your ajax call
Joomla doesn't gives a build in AJAX as part of it's system. my answer is from Josef Leblanc course in lynda.com
http://www.lynda.com/Joomla-1-6-tutorials/Joomla-1-7-Programming-and-Packaging-Extensions/73654-2.html
As I said :
Write this i the frontend JS :
$.ajax({
type: 'GET',
url: 'index.php',
data: {option: 'com_componenetname', task: 'taskname.youroperation', format: 'json', tmpl: 'raw'},
dataType: 'json',
async: true, // can be false also
error: function(xhr, status, error) {
console.log("AJAX ERROR in taskToggleSuceess: ")
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
},
success: function(response){
// on success do something
// use response.valuname for server's data
}
,
complete: function() {
// stop waiting if necessary
}
});
in the backend you should have a file under com_componentname/controllers/taskname.json.php
the file should look like this
class ComponentnameControllerTaskname extends JControllerLegacy (Legacy only J3.0)
{
public function __construct($config = array())
{
parent::__construct($config);
$this->registerTask('operationname', 'functionname');
}
public function functionname() {
// do something in backend
echo json_encode(array(''var1' => val1, 'var2' => val2 ) );
}
}
nibra - I use this in all my joomla sites and its working perfect. your comment was wrong, pease give me my credit back

Resources