Hello i've got this problem with an ajax call in my (newbie) Drupal site. I'm trying to save some data from a form field, by posting it with jQuery to a function in my Drupal module. Here is my code:
// in drupal
function mymodule_menu() {
$items = array();
$items['mymodule/set/data'] = array(
'page callback' => 'mymodule_set_data',
'type' => MENU_SUGGESTED_ITEM,
'access arguments' => array('access content'),
);
return $items;
}
function mymodule_set_data($var) {
drupal_json_output(array('status' => 'OK', 'data' => "return_something"));
}
// in my js file
jQuery("#form_element").on('blur',function(){
jQuery.ajax({
type: 'POST',
url: "mymodule/set/data",
dataType: 'json',
data:{
fu: 'bar'
},
success: function(data) {
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown){
console.log(errorThrown);
}
});
});
Everything goes well, the jQuery get's triggerd, the ajax call is being catched on the server, and i do get the {"status":"OK","data":"return_something"} back from the server. Except for the fact that the status of the call is a 404... :(
I found an solution to my problem.
Ik was moving my app to an other host and there for i needed to change the url the ajax action was calling. I decided to make it dynamic with the following code:
drupal_add_js(array('url' => $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']), 'setting');
I changed my ajax call url into:
"http://"+Drupal.settings.url + "/set/data
This resulted in my JS calling the following URL:
http://host/drupal/?q=mymodule/set/data
instead of the old one:
http://host/drupal/mymodule/set/data
Which was something Drupal did like :)
Still i don't understand why my drupal accepted http://host/drupal/mymodule/set/data, handled my data but returned a 404.
Related
So I am busy with a private coding project right now, but can't seem to get my code to work properly.
I want to in essence, get data from my API and display it on to my HTML page, the data type is set to "jsonp" because of CORS errors( this was the only way I could debug it ), anyone have an idea of how I can get this to return usable data for my project?
function fetch(){
"use strict";var url = "https://api.pandascore.co/lol/champions?token=*my_unique_token*";
$.ajax({
url: url,
type: "GET",
crossDomain: true,
dataType: 'jsonp',
contentType: "application/json; charset=utf-8",
beforeSend: function(xhr){
xhr.setRequestHeader('Access-Control-Allow-Origin','*');
},
success: function(data){
console.log(data);
},
done: function(data){
console.log(data);
},
error: function(error){
console.log(error);
}
});
}
Edit:
This is a parsing problem, I cant get the code to log the success, I can see a response but its for my error log, but it doesn't show the success log, so the data is unusable.
Why not try the vanilla fetch method?
const url = 'https://api.pandascore.co/lol/champions?token=my_unique_token';
fetch(url)
.then(response => response.json())
.then(data => console.log(data))
This code should handle parsing JSON data you receive from pandascore. Fetch is not available in IE11, but there should be some polyfills lying around on the web.
From my controller, I return a JSON data to my Ajax call but it always goes in the error section, even when it's not an error.
jQuery.ajax({
type: 'POST',
url: '/yxcustomer/index/emailpreferences',
data: {"category1": category1,"category2":category2 , "category3":category3,"category4":category4,"category5":category5,"category6":category6,"category7":category7,
"latest1":latest1,"latest2":latest2,"latest3":latest3,"latest4":latest4,
"frequency":frequency,
"email":email,"firstName":firstName , "lastName":lastName},
dataType: "json",
success: function (data) {
console.log("data response success prefe " + JSON.stringify(data));
},
error: function (error) {
console.log("data response error prefe " + JSON.stringify(error));
}
});
Controller code
protected $resultJsonFactory;
public function __construct(
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Framework\App\Action\Context $context
) {
$this->resultJsonFactory = $resultJsonFactory;
parent::__construct($context);
}
public function execute()
{
try{
return $this->resultJsonFactory->create()->setData(['success' => true,'contact'=>json_encode($contact) ,'message' => $this->messageManager->addSuccessMessage("Successfully updated email preferences")]);
} catch (Exception $e) {
return $this->resultJsonFactory->create()->setData(['success' => false,'message' => $this->messageManager->addErrorMessage('Email preferences cannot be updated')]);
}
}
Still that success code
$this->resultJsonFactory->create()->setData(['success' => true,'contact'=>json_encode($contact) ,'message' => $this->messageManager->addSuccessMessage("Successfully updated email preferences")])
Always goes in ajax error part
error: function (error) {}
the response in Ajax is
data response error prefe {"readyState":4,"responseText":"reading contacts with equalto filter\n{\"success\":true,\"contact\":\"{"id":"c74668c8-e886-4592-8950-273a7a6ab72d","email":"an#gmail.com","status":"onboarding","msgPref":"html","source":"api","customSource":"source","created":"2019-03-20T13:10:40-04:00","modified":"2019-03-21T03:44:36-04:00","deleted":false,"fields":[{"fieldId":"0bc403e9000000000000000000000005c10d","content":""},{"fieldId":"0bc403e9000000000000000000000005c10f","content":"Fluid"},{"fieldId":"0bc403e9000000000000000000000005c10e","content":"Men"},{"fieldId":"91c22871-0947-4f63-b067-4290ce18c0a0","content":"Anupam"},{"fieldId":"0bc403e9000000000000000000000005c111","content":""},{"fieldId":"0bc403e9000000000000000000000005c110","content":""},{"fieldId":"0bc403e9000000000000000000000005c113","content":"All"},{"fieldId":"0bc403e9000000000000000000000005c112","content":""},{"fieldId":"0bc403e9000000000000000000000005c115","content":""},{"fieldId":"0bc403e9000000000000000000000005c114","content":"New Arrivals"},{"fieldId":"0bc403e9000000000000000000000005c117","content":"Never Mind"},{"fieldId":"0bc403e9000000000000000000000005c116","content":""},{"fieldId":"0bc403e9000000000000000000000005c0e8","content":""},{"fieldId":"2b0a63f9-cb2d-4fc7-bcc5-06b30b59f8db","content":"singh"}],"numSends":0,"numBounces":0,"numOpens":0,"numClicks":0,"numConversions":0,"conversionAmount":0}\",\"message\":{}}","status":200,"statusText":"OK"}
What am I doing wrong, is there some Magento 2 issue?
In Magento 2, the $resultJsonFactory is used to return the data in JSON format, and you are already doing that which is correct. But, the response goes into the error function of your AJAX request because from the controller, you are encoding the $contact data again in JSON. So, just remove the json_encode like below:
return $this->resultJsonFactory->create()->setData([
'success' => true,
'contact' => $contact,
'message' => $this->messageManager->addSuccessMessage("Successfully updated email preferences")
]);
instead of:
return $this->resultJsonFactory->create()->setData([
'success' => true,
'contact' => json_encode($contact),
'message' => $this->messageManager->addSuccessMessage("Successfully updated email preferences")
]);
Before for submitting I want to send the request to an action. But in return I get 404 not found. The action is obviously there. Also got it in the filters of the controller.
JS:
$('#home-contact').on('beforeSubmit', function(){
$.ajax({
method: 'post',
url: '/site/send-contact',
data: new FormData($(this))[0],
success: function(data){
console.log(data)
}
})
return false
})
Controller filters:
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'signup', 'send-contact'],
'rules' => [
[
'actions' => ['signup', 'send-contact'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
And the action also :
public function actionSendContact()
{
Yii::$app->response->format = Response::FORMAT_JSON;
$model = new Contact();
if($model->load(Yii::$app->request->post()) && $model->save()){
return $data['success'] = Yii::t('app', 'Successfully sent message.');
}
return $data['error'] = Yii::t('app', 'Something went wrong. Please try again.');
}
The scenario happens in the frontend if that matters somehow. Thank you!
Not sure about the 404 you are having as the url in the request is correct and the url that would be generated for the ajax request will be like http://example.com/site/send-contact but only if you are using the 'enablePrettyUrl' => true, for the urlManager component, otherwise it should be like index.php?r=site/index that could only be the reason behind the 404, a better way is to get the url from the form action attribute.
Apart from above,
You are using the new FormData() to send the data with the request like
data: new FormData($(this))[0]
which isn't correct and won't send any FormData with the request as it will return undefined, you can check the console or by using the print_r($_POST) inside the action sendContact once you are done with the 404, it should be
data: new FormData($(this)[0]),
you need to get the form via $(this)[0] and pass to the new FormData().
But this is not enough you have to set the contentType and processData to be false to correctly submit the FormData or you will get the exception in console
Uncaught TypeError: Illegal invocation
So your code should be like
$('#contact-form').on('beforeSubmit', function(){
let url=$(this).attr('action');
let form=$(this)[0];
let data=new FormData(form);
$.ajax({
method: 'post',
url: url,
data:data,
contentType: false, // NEEDED, DON'T OMIT THIS (requires jQuery 1.6+)
processData: false,
success: function(data){
console.log(data)
}
});
return false;
})
EDIT
Note: Above all you should use data:$(form).serialize() simply rather than using new FormData() until unless you are planning to upload files along with the form using ajax.
URL in JavaScript seems to be not fully specified.
The valid way would be:
url: 'index.php?r=site/send-contact',
But this works only if your index.php is in root folder.
To make it work with any situation (e.g., index.php is not in root), then you have different solutions. I personally like to use this:
Declare action and id in your form:
Example:
$form = ActiveForm::begin([
'action' => ['site/send-contact'],
'id' => 'my-form',
]);
Use a link (that is generated by Yii2 itself) in your JS code:
Example:
$('#home-contact').on('beforeSubmit', function() {
$.ajax({
method: 'post',
url: $('#my-form').attr('action'),
data: new FormData($(this))[0],
success: function(data) {
console.log(data)
}
});
return false;
});
This should work in all cases, whenever your files are.
Hope that helps!
did you add 'enableAjaxValidation' => true or add action name in active form?
$form = ActiveForm::begin([
'action' => ['controller/action'],
'enableAjaxValidation' => true
]);
I'm making a POST request, using ajax, to a Zend Controller.
$.ajax({
type: 'POST',
data: data,
dataType: "json",
error: function(e){
console.log(e);
}
success: function(msg){
if(msg.success){
//doesn't reach here. I'm getting redirected
console.log('success');
}
}
});
In zend, I have the following line:
$this->jsonResponse(array('success' => true, 'embed' => 'some text here'));
My problem is that I'm getting redirected to the json response page (that's the actual page) which contains the response. The response is correct, but I don't want to be redirected. I don't know what's happening and why is this happening.
In controller write these codes
$this->_helper->layout()->disableLayout(); //to disable layout
$this->view->jsonResponse = json_encode(array(
'success' => true,
'embed' => 'some text here'
)); // encode array
And in view write this line
echo $this->jsonResponse;
I'm sending a simple data back from the server to the client.
app.post('/user', function (req, res) {
var userName = "John";
res.end(JSON.stringify({"error":"", "user": userName}));
});
$.ajax({
type: "POST",
...
contentType : 'application/json',
dataType: "json"
})
.done(function(data) {
// send join message
var resData = JSON.parse(data);
alert("hello"); // this doesn't show up
});
});
});
But in the browser console, I get this error - "Uncaught SyntaxError: Unexpected token o".
If I do JSON.stringify and JSON.parse on the content, it works fine.
alert(JSON.parse (JSON.stringify({"error":"", "user": userName})).user);
And also, .done works fine without a data payload from the server i.e. the alert("hello") works.
So, I'm guessing something fishy is happening while sending data within res.end(). Please help.
While at it, it would be nice if you can also tell me how to do the same using res.json() and which one is preferable.
The problem here is that you set dataType: 'json' in your jQuery request. This causes the response from the server to be automatically parsed as JSON, so it will return the object rather than the raw server response.