In some circumstance I need to add POST parameter programmatically to AJAX request.
I'm trying something like this:
$(document).ajaxSend(function(event, jqXHR, ajaxOptions) {
ajaxOptions.data = "additional_key=additional_value&" + ajaxOptions.data;
ajaxOptions.context.data = "additional_key=additional_value&" + ajaxOptions.context.data;
console.log(ajaxOptions, 'ajaxOptions');
});
But additional_key isn't appear in $_POST array.
You can use ajaxPrefilter for this :
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (originalOptions.type !== 'POST' || options.type !== 'POST') {
return;
}
options.data = $.extend(originalOptions.data, { yourdata : yourvalue });
});
See http://api.jquery.com/jquery.ajaxprefilter/ for more infos.
testing your above code gave me an error that ajaxOptions.context was undefined.
First, I'd advise that you check for existence first: (Assuming that context is ever going to be defined)
if(ajaxOptions.context) {
ajaxOptions.context.data = "additional_key=additional_value&" + ajaxOptions.context.data;
} else {
ajaxOptions.data = "additional_key=additional_value&" + ajaxOptions.data;
}
Sending off a mock AJAX request showed me that the data is being passed through when inspected in Firebug.
I tested the code by removing the context line, and it seemed to work:
Code:
$(document).ajaxSend(function(event, jqXHR, ajaxOptions) {
if(ajaxOptions.context) {
ajaxOptions.context.data = "additional_key=additional_value&" + ajaxOptions.context.data;
} else {
ajaxOptions.data = "additional_key=additional_value&" + ajaxOptions.data;
}
});
$.ajax({
'url': 'test.php',
'data': {'foo':'bar'},
'type': 'POST'
});
Inspection:
Key Value
additional_key additional_value
foo bar
Edit: Tested with JQuery 1.7.1 I've noticed that you're running a lower version of jQuery.
$(document).ready(function() {
$(document).ajaxSend(function(event, jqXHR, ajaxOptions) {
if (ajaxOptions.extraData) {
ajaxOptions.extraData.additional_key = 'additional_value';
}
});
});
This only work for me (jQuery 1.4.4)
Related
I build following JavaScript part and everything works fine. But I'm not sure if the code is completely right. Because in my script I only use success: function() but I don't use error. Is it a MUST to have error in a jQuery AJAX call?
Currently I'm catching the errors in my php controller function and echo them in the success part.
$(document)
.ready(function() {
var groupName = '';
var groupid = '';
$(".grp")
.click(function() {
$('.text-danger')
.html('');
groupName = $(this)
.data('groupname');
groupid = $(this)
.attr('id');
$('.text')
.html(groupName);
$('#dataModal')
.modal({
show: true
});
});
jQuery(".grpval")
.click(function(e) {
e.preventDefault();
jQuery.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]')
.attr('content')
}
, });
jQuery.ajax({
url: "{{ route('request_group') }}"
, method: 'post'
, data: {
'Gruppe': groupid
}
, success: function(data) {
if (typeof data.successsuccess != 'undefined') {
jQuery('.alert-success')
.show();
jQuery('.alert-success')
.html('<p>' + data.successsuccess + '</p>');
$('#dataModal')
.modal('toggle');
window.scrollTo(500, 0);
} else if (typeof data.successdberror != 'undefined') {
jQuery('.alert-danger')
.show();
jQuery('.alert-danger')
.html('<p>' + data.successdberror + '</p>');
$('#dataModal')
.modal('toggle');
window.scrollTo(500, 0);
} else {
jQuery.each(data.errors, function(key, value) {
jQuery('.alert-danger')
.show();
jQuery('.alert-danger')
.html('<p>' + value + '</p>');
$('#dataModal')
.modal('toggle');
window.scrollTo(500, 0);
});
}
}
});
});
});
EDIT: Here is the function from my Controller:
public function setGroupRequest(Request $request){
$validator = \Validator::make($request->all(), [
'Gruppe' => [new ValidRequest]
]);
$groupid = $request->input('Gruppe');
if ($validator->fails())
{
return response()->json(['errors'=>$validator->errors()->all()]);
}
try{
$groups_request = new GroupRequest();
$groups_request->idgroups = $groupid;
$groups_request->iduser = Auth::id();
$groups_request->request_active = 1;
$groups_request->save();
$db_status = 'success';
}catch(\Exception $e){
$db_status = 'error';
}
if($db_status == 'success'){
return response()->json(['successsuccess'=>'Record is successfully added']);
}else{
return response()->json(['successdberror'=>'DB Error! Values could not be saved.']);
}
}
Error handling is required as you never know different things on the internet might result in failure of request for example,
Network failure.
Lost database connection
Unauthorised access/access denied
Any variable being not defined
There is nothing wrong in your way of writing PHP error in success, but writing it in $ajax error callback function is preferred as it helps in separating error & success logic.
In fact you can add a jquery error callback function as well to your $ajax which will handle all the errors originating from above mentioned internet failures.
You can add error function, which will receive any type of error coming from backend.
jQuery.ajax({
url: "{{ route('request_group') }}",
method: 'data: {
'Gruppe': groupid
},
success: function(data) {
//code here
},
error: function (jqXHR, exception) {
//error handling
}
})
In your PHP file,
if ($query) {
echo "success"; //whatever you want to show on success.
} else {
die(header("HTTP/1.0 404 Not Found")); //Throw an error on failure
}
This way you can catch PHP error as well as any internet Network errors in your jquery ajax.
On a page I have a list of dates which I want to edit via AJAX.
Example:
<li>January 2015<a data-update_url="/frame_date/22/update/" class="update" id="update_framedate_22" href="javascript:void(0)">Edit</a>
When the user clicks on the Edit link, I catch element id and the edit link.
Than AJAX requests the update form from the server. And now I have to place the form instead of the element with the mentioned id.
In other words, in frame_date_update_show_get I need element's id. In the example below, I keep it in the global variable date_id. But inside me there is a protest: I was always taught that global variables is a bad practice. But in this case I don't know how to get along without the global variable date_id.
Could you give me some piece of advice: is my code acceptable or there is a better way to cope with the problem.
function frame_date_update_show_get(data){
$("#" + date_id).replaceWith(data);
}
function frame_date_update_get_data(){
date_id = this.getAttribute('id')
var cuaghtUrl = this.getAttribute('data-update_url');
$.ajax({
method: 'get',
url: cuaghtUrl,
success: frame_date_update_show_get,
error: fail
});
}
var date_id = ""
Use an anonymous function as success callback function and then call frame_date_update_show_get with an additional date_id parameter:
function frame_date_update_show_get(data, date_id) {
$("#" + date_id).replaceWith(data);
}
function frame_date_update_get_data() {
var date_id = this.getAttribute('id')
var cuaghtUrl = this.getAttribute('data-update_url');
$.ajax({
method: 'get',
url: cuaghtUrl,
success: function(data) {
frame_date_update_show_get(data, date_id);
},
error: fail
});
}
I would use contenteditable combined with AJAX this way:
function dateChange(options){
switch( options.action ) {
case 'update':
if( options.id && options.text && options.updateUrl ) {
$.ajax({
method: 'post',
url: options.updateUrl,
data: {
id: options.id,
html: options.text
},
success: function(response) {
options.element.html( response );
options.element.removeClass('editing');
},
error: function(err) {
console.log( 'request failed: ' + err.text );
}
});
};
break;
default:
console.log( 'action invalid' );
return false;
break;
};
};
var editTimeout = null;
$('li[data-update-url]').on('input', function(e) {
var thisText = $(this);
thisText.addClass('editing');
clearTimeout( editTimeout );
editTimeout = setTimeout(function() {
var updateUrl = thisText.data('updateUrl');
var id = thisText.data('id');
dateChange({
'action': 'update',
'element': thisText,
'id': id,
'updateUrl': updateUrl,
'text': thisText.html()
});
}, 1000);
});
.editing {
color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-update-url="/echo/html/" data-id="update_framedate_22" contenteditable>January 2015</li>
</ul>
Check how it works on JSFiddle.
This code would be easy to expand for other actions you may need, as delete, add.
The beforeSubmit function in my jQuery Form plugin needs to check whether the selected file already exists on the server. Here's that relevant code:
$('#frmSermonUpload').ajaxForm({
beforeSubmit: function() {
// Reset errors and clear messages
ClearForm(false);
var formValid = true,
fileExists = CheckFileExists();
console.log('beforeSubmit fileExists: ' + fileExists);
if (fileExists === 'true') {
$('#uploadedFile').addClass('inputError');
$('#fileErrorMsg').append(' A file with that name already exists on the server.');
formValid = false;
} else {
if (!ValidateUploadForm()) {
formValid = false;
}
}
console.log('formValid: ' + formValid);
if (!formValid) {
return false;
}
},
...
Here's the CheckFileExists() function:
function CheckFileExists() {
var fileName = $('#uploadedFile').val().replace(/C:\\fakepath\\/i, ''),
dataString;
dataString = 'checkFileExists=' + fileName;
console.log('fileName: ' + fileName);
console.log('dataString: ' + dataString);
$.ajax({
type: 'POST',
url: '../scripts/sermonUpload.php',
data: dataString,
success: function(serverResult) {
console.log('serverResult: ' + serverResult);
if (serverResult === 'existsTrue') {
return 'true';
} else {
return 'false';
}
},
error: function(xhr, status, error) {
alert('An error occurred while attempting to determine if the selected file exists. Please try again.);
}
});
//console.log('Current value of returnResult: ' + returnResult);
//return returnResult;
}
As you can see I'm using console output to check what's going on. In the CheckFileExists() function, fileName and dataString are being reported correctly. On the PHP side, I know that the POST data is getting there due to some logging I've got going on there.
Here's the PHP code that uses the POST data:
if (isset($_POST['checkFileExists']) && $_POST['checkFileExists'] !== '') {
$log->lwrite('**Checking if file exists.**');
$fileToCheck = $targetPath . $_POST['checkFileExists'];
$log->lwrite('file_exists: ' . file_exists($fileToCheck));
if (file_exists($fileToCheck)) {
echo 'existsTrue';
} else {
echo 'existsFalse';
}
}
What's happening is, in the console, the line console.log('beforeSubmit fileExists: ' + fileExists); is returning "undefined" (beforeSubmit fileExists: undefined).
Here's all of the console output for an upload where the file already exists, so the beforeSubmit should be stopped:
fileName: 042913sermon.mp3
dataString; checkFileExists=042913sermon.mp3
beforeSubmit fileExists: undefined
formValid: true
serverResult: existsTrue
It must be significant that the serverResult line is displaying after everything else. Does that have to do with how long the ajax call takes? If so, is there a way to delay the rest of the script until the ajax call is done executing?
UPDATE
As aorlando pointed out, the order of the console output signified that I needed to add async: false to my $.ajax call. After doing so, the console output was correct, but the function CheckFileExists() is still getting reported as undefined in beforeSubmit.
Ok. Now the problem is the scope of return.
If you use "async: false" you can return in this way (not so elegant)
var returnValue='';
$.ajax({
type: 'POST',
url: '../scripts/sermonUpload.php',
data: dataString,
async: false,
success: function(serverResult) {
console.log('serverResult: ' + serverResult);
if (serverResult === 'existsTrue') {
returnValue = 'true';
} else {
returnValue= 'false';
}
},
error: function(xhr, status, error) {
alert('An error occurred while attempting to determine if the selected file exists. Please try again.);
}
});
return returnValue;
You must declare a var returnValue out of the scope of the ajax call. Inside the ajax function you can modify the value of returnValue;
This is a solution which use closure, a quite complex javascript feature. Further read something about scope of a variable in javascript: What is the scope of variables in JavaScript?
This is not a very nice solution; is better if you call a function inside "success" function of ajax call as my previous example.
That's all folks!
You are using an AJAX async call.
Your method CheckFileExists()n return a value before the ajax call complete.
So the simplest solutions is to use:
$.ajax({
type: 'POST',
url: '../scripts/sermonUpload.php',
data: dataString,
async: false ...
if you want to use async call (the default as you can see: http://api.jquery.com/jQuery.ajax/
you must call (for ex.) a postcall function in the success function of the ajax call:
success: function(serverResult) {
console.log('serverResult: ' + serverResult);
if (serverResult === 'existsTrue') {
postFn('true');
} else {
postFn('false');
}
}, ...
Be carefull with the scope of the postFn
funcion postFn(_result){
console.log(_result);
}
I hope to be clear.
That's all folks!
When I am going to submit data using AJAX that time IE display error like object doesn't support this property or method
$("#savebasicInfo").live("click",function()
{
var lookingfor='';
var interestedIn='';
$(".lookingfor").each(function(i)
{
if(this.checked == true)
{
lookingfor= lookingfor+","+$(this).val().trim(); // error found here
}
i++;
});
$(".interestedIn").each(function(j)
{
if(this.checked == true)
{
interestedIn= interestedIn+","+$(this).val().trim(); // error found here
}
j++;
});
$.ajax(
{
type: "POST",
url: $("#cfgRoot").val()+'/accounts/basicInfoPost.php',
data:
{
city:$("#city").val().trim(),
hometown:$("#hometown").val().trim(),
interestedIn:interestedIn,
relationship:$("#relationship").val().trim(),
lookingfor:lookingfor,
political:$("#political").val().trim(),
religious:$("#religious").val().trim()
},
success: function(responce)
{
if(responce == 1)
{
$("#basicProfileMain").load("basicInfoMain.php");
$("#basicProfileMain").css({"height":"auto"});
}
}
});
});
You cannot 'trim' a string as such in JavaScript as there is no trim method in core js. However, you can use jQuery's trim function.
$.trim($(this).val())
How can I handle errors in AJAX?
In my code, the else condition containing console.log is not executed even when the departments.json file is not loaded. I checked it by deleting the departments.json file from where it is loaded into the code.
My code is:
$.getJSON("departments.json?" + new Date().getTime(), {}, function(departments, status, xhr) {
if (xhr.status == 200) {
var numericDepts = [];
var nonNumericDepts = [];
for(dept in departments) {
$("#kss-spinner").css({'display':'none'});
if (isNaN(departments[dept].depNo)) {
if (isNaN(parseInt(departments[dept].depNo,10)))
nonNumericDepts[nonNumericDepts.length] = departments[dept];
else
numericDepts[numericDepts.length] = departments[dept];
}
else
numericDepts[numericDepts.length] = departments[dept];
}
numericDepts.sort(cmp_dept);
nonNumericDepts.sort(function(dept1,dept2) {
return dept1.depNo.toLowerCase() - dept2.depNo.toLowerCase();
});
departments.sort(cmp_dept);
var k = 0;
$.each(numericDepts.concat(nonNumericDepts), function() {
if (k % 2 == 0) {
$('<p class="odd" onClick="selectTag(this,\'' + this.id + '\', 1)">' + this.depNo + '</p>').appendTo($(".scroller", $("#br1")));
}
else {
$('<p class="even" onClick="selectTag(this,\'' + this.id + '\', 1)">' + this.depNo + '</p>').appendTo($(".scroller", $("#br1")));
}
k++;
});
$("#kss-spinner").css({'display':'none'});
}
else {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText)
console.log(xhr.statusText);
console.log('json not loaded');
}
});
You could just use the generic ajax() function:
$.ajax({
url: url,
dataType: 'json',
data: data,
success: successCallback,
error: errorCallback
});
You will need to use the fail() method in order to accomplish that.
Example:
$.get("test.php")
.done(function(){ alert("$.get succeeded"); })
.fail(function(){ alert("$.get failed!"); });
if you need a generic error handler use
$.ajaxSetup({
error: function(xhr, status, error) {
// your handling code goes here
}
});
JQuery's getJSON function is an abstraction over the regular .ajax() method - but it excludes the error callback.
Basically, the function you define is only called if the call is successful (that's why it never gets to the else part).
To handle errors, set an error handler before like this:
$.ajaxError(function(event, jqXHR, ajaxSettings, thrownError) { alert("error");});
Whenever an AJAX request completes with an error, the function will be called.
You can also append the .error at the end of your getJSON call:
$.getJSON("example.json", function() {
(...)
}).error(function() { (...) });
The $.getJSON() function is just a special purpose version of the more general .ajax() function.
.ajax() function will give you the extra functionality you desire (such as an error function). You can read more documentation here http://api.jquery.com/jQuery.ajax/
$.ajax({
url: "departments.json?" + new Date().getTime(),
dataType: 'json',
success: function(departments){
var numericDepts = [];
var nonNumericDepts = [];
for(dept in departments)
{
$("#kss-spinner").css({'display':'none'});
if(isNaN(departments[dept].depNo))
{
if(isNaN(parseInt(departments[dept].depNo,10)))
nonNumericDepts[nonNumericDepts.length]=departments[dept];
else
numericDepts[numericDepts.length]=departments[dept];
}
else
numericDepts[numericDepts.length]=departments[dept];
}
numericDepts.sort(cmp_dept);
nonNumericDepts.sort(function(dept1,dept2) {
return dept1.depNo.toLowerCase() - dept2.depNo.toLowerCase();
});
departments.sort(cmp_dept);
var k=0;
$.each(numericDepts.concat(nonNumericDepts),function(){
if(k%2==0){
$('<p class="odd" onClick="selectTag(this,\''+this.id+'\',1)">'+this.depNo+'</p>').appendTo($(".scroller",$("#br1")));
} else {
$('<p class="even" onClick="selectTag(this,\''+this.id+'\',1)">'+this.depNo+'</p>').appendTo($(".scroller",$("#br1")));
}
k++;
});
$("#kss-spinner").css({'display':'none'});
},
error: function(xhr, textStatus, errorThrown) {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText)
console.log(xhr.statusText);
console.log('json not loaded');
}
});