Ive been struggling to pass my parameters from a functions but I just really can't figure out where did I go wrong. I have a function that have a parameters that I want to pass to my postData to display datas in my jQgrid. Here's my function code with parameters:
function getTID(hdrID){
var selected = $('#editTallyHdr').val();
var hdrID = '';
var hdrNo = '';
var nameFlag=0;
var par_ams = {
"SessionID": $.cookie("SessionID"),
"dataType": "data"
};
$.ajax({
type: 'GET',
url: 'processjson.php?' + $.param({path:'getData/tallyHdr',json:JSON.stringify(par_ams)}),
dataType: primeSettings.ajaxDataType,
success: function(data) {
if ('error' in data)
{
showMessage('ERROR: ' + data["error"]["msg"]);
}
else{
$.each(data['result']['main']['rowdata'], function(rowIndex, rowDataValue) {
$.each(rowDataValue, function(columnIndex, rowArrayValue) {
var fldName = data['result']['main']['metadata']['fields'][columnIndex].name;
if (fldName == 'transaction_id'){
hdrID = rowArrayValue;
}
if (fldName == 'transaction_num'){
hdrNo = rowArrayValue;
if(selected == hdrNo){
nameFlag =1;
};
}
});
});
}
}
});
return (hdrID);
}
and here is my jQgrid code where I call that function to get it's parameter:
$("#tblPlank").jqGrid({
url: '',
datatype: 'local',
jsonReader : {
.
.
.
serializeGridData: function(postData) {
var ctr =0;
var filt=[];
var c=[];
var jsonParams = {
'SessionID': $.cookie("SessionID"),
'dataType': 'data',
'transaction_id':getTID(hdrID),
'filters': c,
'lines':plank_data,
'recordLimit': postData.rows,
'recordOffset': postData.rows * (postData.page - 1),
'rowDataAsObjects': false,
'queryRowCount': true,
'sort_fields': postData.sidx
};
.
.// some code here
.
.
return 'json=' + JSON.stringify(jsonParams);
},
loadError: function(xhr, msg, e) {
showMessage('HTTP error: ' + JSON.stringify(msg) + '.');
},
colNames:[...],
colModel:[
........................
],
.
.
.
caption: "Tally Transaction Details/Lines"
I also have another code where I want to get that parameter. Here's the last code:
var par_ams = {
"SessionID": $.cookie("SessionID"),
"dataType": "data",
"transaction_id": getTID(hdrTID)
}
$('#tblPlank').setGridParam({
url:'processjson.php?path=' + encodeURI('getData/tallyLnDtl') + '&json=' + encodeURI(JSON.stringify(par_ams)),
datatype: primeSettings.ajaxDataType,
});
$('#tblPlank').trigger('reloadGrid');
Those codes below that function getTID(hdrID) cant retrieve the parameter, it shows empty. This maybe simple to anyone, but I really need help on this.. been working with this for quite long hours.
This is a very common misunderstanding. I've probably answered 15 of these questions in the last two weeks alone. An ajax call is an asynchronous call. That means that when you make the ajax call, it just STARTs the request. Then, while that request goes in the background, your code immediately keeps executing. That means that your function getTID() returns before the ajax call has even completed and it's value is not yet known. Thus, there is no way to return the response value from the ajax function when you return from getTID() as it is simply not known yet.
To work with asynchronous function calls (like ajax calls), you have to change your programming style to something that works asynchronously. In this case, the response to your ajax call is ONLY known in the success handler for the ajax all. So, you have to restructure your code to continue on with the execution of your processing and the handling of the ajax response from the success handler. If you have only a little bit of work to do, then you can put it all in the success handler. If you have a lot of work to do, then you can put all the rest of that work in a function call and call it from the success handler.
The problem is that you're doing an ajax-request (asynchronous request). Then the function does not wait for an answer to arrive, but just continues and returns hdrID (which isn't set at the time). After that a response comes in, and the success-method is called, which sets hdrID to the appropiate value.
The common way to solve this is to execute a specific function with the desired values when the success-method is executed. It's too much code to look into, but it could go something like this:
function fetchContent(continueFunction) {
$.ajax(params).success(function(reply) {
// retrieve desired params from reply
continueFunction(retrievedParameters);
}
}
What you could do is define getTID to take in a callback to execute once it has the id, for instance
function getTID(hdrID, callback) {
//ajax stuff....
success: function (data) {
// Error checks, etc
hdrID = //something dependent on data
callback(hdrID); // THIS IS THE IMPORTANT PART
}
the callback will execute after the request has returned, when it is safe to use the data returned from the ajax request that will be needed in the callback. You could wrap all of the code that needs the return value of the request in the callback, for example
getTID(hdrID, function (ID) {
var params = {
"SessionID": $.cookie("SessionID"),
"dataType": "data",
"transaction_id": ID //USE ID
}
$('#tblPlank').setGridParam({
url:'processjson.php?path=' + encodeURI('getData/tallyLnDtl') + '&json=' + encodeURI(JSON.stringify(par_ams)),
datatype: primeSettings.ajaxDataType,
});
$('#tblPlank').trigger('reloadGrid');
};
});
Related
I have function that search for every element with a specific class:
$("#stepSurveyCtnId .questionCtnClass").each(function () {}
Inside each step, I check if a question is of type customer:
var type = $(this).children().data("question-type");
var isCustomerQuestion = false;
switch (type) {
case "Name":
case "Email":
isCustomerQuestion = true;
break;
}
If it's customer type, I get the next id of the customer's table from the database:
if(isCustomerQuestion) {
if (customerId == -1) {
$.ajax({
method: "POST",
url: urlCustomerCreate,
success: function (ajaxData) {
customerId = ajaxData.NumericValue;
}
});
}
}
The issue is that in the second iteration of the .each() function, customerId is still = -1, when it should be 1305 for example.
It seems that the execution don't stop in the $.ajax call, or the iterations are executed at the same time and the second iteration don't receive the customerId from the first iteration.
I'm still not 100% clear on sure on how everything is structured for you, but here is one way of handling asynchronicity in JavaScript (adapted from #ShubHam's answer)
function handleQuestion(questionElements, index, customerId) {
if (questionIndex >= questionElements.length) return;
var type = $(this).children().data("question-type");
var isCustomerQuestion = false;
switch (type) {
case "Name":
case "Email":
isCustomerQuestion = true;
break;
}
if(isCustomerQuestion) {
if (customerId == -1) {
$.ajax({
method: "POST",
url: urlCustomerCreate,
success: function (ajaxData) {
handleQuestion(questionElements, questionIndex + 1, ajaxData.NumericValue);
}
});
} else {
// Have ID now
handleQuestion(questionElements, questionIndex + 1, customerId);
}
}
}
// Go
handleQuestion($("#stepSurveyCtnId .questionCtnClass"), 0, -1);
This will only continue to the next iteration after the success callback has been triggered.
Put logic inside one function (say function 1) and ajax call inside other function.
Call ajax function from function 1. Inside success call function 1 with required params
Update (example added):
var x=['a','b','c']
var elm=document.getElementById('demo')
x.forEach(function(temp){
elm.innerHTML=elm.innerHTML+temp
})
<div id='demo'></div>
This can be converted to new logic as
var x=['a','b','c']
function sethtml(temp,length,maxlength){
//here ajax call can be placed
var elm=document.getElementById('demo')
elm.innerHTML=elm.innerHTML+temp
//inside success function of ajax
traverse(length+1,maxlength)
}
function traverse(length,maxlength){
if(length>=maxlength)
{
//all calls done next steps to perform
}else{
sethtml(x[length],length,maxlength)
}
}
traverse(0,x.length)
<div id='demo'></div>
Advice to be considered from Jamie-Day in comments: Check your logic for scope of improvement. Accessing db results in for each kind of scenario generally can be avoided(ideally it should be avoided for better user experience)
Change your ajax code. add "async: false" so that each code next to ajax will wait for ajax result
if(isCustomerQuestion) {
if (customerId == -1) {
$.ajax({
method: "POST",
async: false,
url: urlCustomerCreate,
success: function (ajaxData) {
customerId = ajaxData.NumericValue;
}
});
}
}
First, you need to think asynchronously.
Code that need to run after the ajax should be called from the success function. You also want to add error function to handle server errors.
Second, to improve speed and bandwidth I'd reduce number of AJAX calls to a single one, by joining all IDs together in a single AJAX request.
It require server-side changes and you did not provide the server-side, so I'll leave server side to you.
// Prepare ajax call
var customerData = [];
var customerCreateData = [];
$("#stepSurveyCtnId .questionCtnClass").each(function () {
var type = $(this).children().data("question-type");
var isCustomerQuestion = false;
switch (type) {
case "Name":
case "Email":
isCustomerQuestion = true;
break;
}
// Set customerId and customerCreateData
if(isCustomerQuestion) {
if (customerId == -1) {
customerCreateData.push(customerCreateData);
}
}
}); // end each
if (customerCreateData.length) {
$.ajax({
method: "POST",
url: urlCustomerCreate,
data: customerCreateData,
success: function (ajaxData) {
customerData = ajaxData.customerData;
doAmazingThingsWithCustomers(customerData);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Server error: ' + errorThrown);
}
});
}
The first A in AJAX stands for Asynchronous which means that the ajax calls would get executed and would not wait for the call to finish. This way we can let users interact with other elements on the page and provide a good user experience.
If we make the AJAX calls asynchronous by setting the async option to false, then the browser would wait for the ajax call to complete and users would not be able to interact with the elements until the call has completed. With the increase in number of calls, this blockage time would increase.
I would suggest you find a better alternative than this.
I am having trouble getting the errorCount property to increase during code execution. The problem I am having is occurring inside of the $.ajax request, more specifically the addError() method.
If I use the following code below to check the current count of errorCount it always returns 0 even though I have manually created an error to occur. But inside of the ajax method after I call addError() and then check the value of errorCount it shows 1 like it should. What did I do wrong?
var boom = new test(settings, formData, search);
console.log(boom.errorCount);
boom.queueCalls(settings);
console.log(boom);
console.log(boom.errorCount);
Here is the object code:
function test(a, b, c) {
this.settings = a;
this.formData = b;
this.search = c;
this.errorCount = 0;
}
test.prototype = {
constructor: test,
queueEmails:function(settings, formData, search) {
var url = '/example-url-endpoint';
var data = {postData: settings + "&" + formData + "&" + search};
this.sendRequest(url, data);
},
queueCalls:function(settings) {
var url = '/example-url-endpoint2';
this.sendRequest(url, settings);
},
addMessage:function(response) {
flashMessage(response.Message, response.Result);
},
addError:function() {
this.errorCount++;
},
sendRequest:function(url, data) {
var blah = this;
j$.ajax({
type: "POST",
url: url,
data: data,
dataType: 'json',
success: function(data) {
response = JSON.parse(data);
if(response.Result != 'error') {
blah.addMessage(response);
} else {
blah.addMessage(response);
blah.addError();
console.log(blah.errorCount);
}
},
error: function(e, textStatus, errorThrown) {
blah.addError();
console.log(blah.errorCount);
alert("There was an error creating the queue");
}
});
}
}
The problem is you are doing an asynchronous (AJAX) call. When you call the queueCalls function, it makes the AJAX call, then runs your console.log statements. It does not wait until the AJAX call is done, and you have received your errors to run the console statements. If you want to do that, look at the jQuery documentation for .ajax(), and either make your AJAX call not asynchronous, or put your console statements in a .done() event handler that will fire after the AJAX call is complete.
I am more of a java developer and am having difficulty with javascript callback. I am wondering if any experts here would help me out of my struggle with this code.
I am trying to pull our locations from db and populating in an array. On first load i am trying to refresh all locations and I am having trouble to control the flow of execution and loading values. Below is the code and I have put in the output at the end.
JQUERY CODE:
// load all locations on first load.
refreshLocations();
$("#locInput").autocomplete({source: locationData});
}); // end of document.ready
// function to refresh all locations.
function refreshLocations() {
getLocationArray(function(){
console.log("firing after getting location array");
});
}
// function to get the required array of locations.
function getLocationArray() {
getJsonValues("GET", "getLocalityData.php", "", getLocalityFromJson);
}
// function to pick up localities from json.
function getLocalityFromJson(json){
if (!json) {
console.log("====> JSON IS NOT DEFINED !! <====");
return;
} else {
console.log("json is defined so processing...");
var i = 0;
$.each(json.listinginfo, function() {
var loc = json.listinginfo[i].locality;
locationArray[i] = loc;
console.log("added location ->" + locationArray[i]);
i++;
});
}
//return locationArray;
}
// function to get raw json from db.
function getJsonValues(type, url, query, getLocalityFromJson) {
var json;
// if the previous request is still pending abort.
if (req !== null)
req.abort();
var searchString = "";
if (query !== "") {
searchString = "searchStr" + query;
}
console.log("searchString : (" + query + ")");
req = $.ajax({
type: type,
url: url,
data: searchString,
contentType: "application/json; charset=utf-8",
dataType: "text",
success: function(result) {
json = JSON.parse(result);
console.log("========start of json
return============");
console.log(JSON.stringify(json));
console.log("========end of json
return============");
//return json;
}
});
getLocalityFromJson(json);
return json;
}
the output from above code is as follows:
searchString : () (18:25:36:473)
at locality1.php:74
====> JSON IS NOT DEFINED !! <==== (18:25:36:518)
at locality1.php:48
========start of json return============ (18:25:37:606)
at locality1.php:83
{"listinginfo":[{"listing":"1","locality":"birmingham"},
{"listing":"2","locality":"oxford"}]} (18:25:37:624)
at locality1.php:84
========end of json return============ (18:25:37:642)
at locality1.php:85
>
Help will be greatly appreciated.
call getLocalityFromJson(json); inside your success callback
function getJsonValues(type, url, query, getLocalityFromJson) {
var json;
// if the previous request is still pending abort.
if (req !== null)
req.abort();
var searchString = "";
if (query !== "") {
searchString = "searchStr" + query;
}
console.log("searchString : (" + query + ")");
req = $.ajax({
type: type,
url: url,
data: searchString,
contentType: "application/json; charset=utf-8",
dataType: "text",
success: function(result) {
json = JSON.parse(result);
console.log("========start of json return============");
console.log(JSON.stringify(json));
console.log("========end of json return============");
//return json;
getLocalityFromJson(json);
}
});
}
You need to call getLocalityFromJson(json) and return json inside your ajax success function. Ajax requests are asynchronous, there's no guarantee that the request will be finished by the time you get to the lines getLocalityFromJson(json); return(json); where they are currently.
The call back functions from a jquery ajax call is complete, failure, success, etc..
Success is called after a request is successful,
Failure is called if theres something like an error 500, or a 404, or w/e.
Complete is Always called after a ajax call.
If you want your code to just follow sequence like in java, throw async: false into your ajax call.. but I wouldnt' recommend this as it defeats the purpose of using this method, and also locks up your browser.
You should make sure you are waiting for the request to finish before moving on - so put code in the success function that you want to run AFTER the request has finished fetching your data.
I think you need to remember Ajax is running async, so you need to follow this thread to execute your refresh.
function IsSwap()
{
var urlString = "<%= System.Web.VirtualPathUtility.ToAbsolute("~/mvc/Indications.cfc/GetModelType")%>";
var id =
{
id : GetGUIDValue()
}
$.ajax({
type: "POST",
url: urlString,
data: id,
success: function(data) {
if (data.toString() == 'SwapModel')
{
return true;
}
}
});
Expected result is true. I can alert right before the return so I know it's getting to that point fine. In another function, I tried to get my bool and use it like this:
var isSwap = IsSwap();
if (isSwap)
and it keeps saying isSwap is undefined. Why?
You are using ajax requests, which are asynchronous. You can't return value from an ajax request. Try this instead:
function IsSwap()
{
var urlString = "<%= System.Web.VirtualPathUtility.ToAbsolute("~/mvc/Indications.cfc/GetModelType")%>";
var id =
{
id : GetGUIDValue()
}
$.ajax({
type: "POST",
url: urlString,
data: id,
success: function(data) {
if (data.toString() == 'SwapModel')
{
ResultIsTrue(); // call another function.
}
}
});
After execution, instead of using this:
var isSwap = IsSwap();
if (isSwap){
// Do Somethinh
}
Try that:
IsSwap();
function ResultIsTrue(){
// Do Same Thing
}
You can't return from an ajax call like that.
Essentially what you're doing is returning true from the inner function.
You should just call whatever code you need in the success method as that's the only time you can guarantee that the ajax call has completed.
The AJAX request is asynchronous, meaning that IsSwap will return before the response to the AJAX request.
Whatever you need to do based on isSwap, you should do in the success handler of your AJAX request.
UPDATE: This last paragraph is incorrect about it working, but worth noting about synchronous not being recommended:
Alternatively, you could make the AJAX request synchronous (by adding async:false to the AJAX options) and keep it how you have it - however I wouldn't recommend this as your browser will 'freeze' whilst it waits for the response.
Check this line:
var urlString = "<%= System.Web.VirtualPathUtility.ToAbsolute("~/mvc/Indications.cfc/GetModelType")%>";
Try using single quotes like so:
var urlString = '<%= System.Web.VirtualPathUtility.ToAbsolute("~/mvc/Indications.cfc/GetModelType")%>';
Your double quotes inside double quotes is most likely your problem.
I have this function that embeds flash :
function embedswfile(target, swf, base, width, height) {//dosomething}
And I want to call the function like this
embedSwf("flashgame",decode("<?=base64_encode($path['location'])?>"),decode("<?=base64_encode($path['base_directory'])?>"),"800","600" )
The idea is that whenever someone looks for any swf inside my website,he wont find anything clean.I will change the encoding algorithm,but this is just temporary. In order for that function to work,whenever I call the function 'decode' it must return a single value. PHP contains
<?php
echo base64_decode($_POST['s']);
?>
I tried this but it still wont work
var globvar;
function processdata(newmsg) {
globvar = newmsg;
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
processdata(newmsg);
}
});
return globvar;
}
Important:
Forget about using Ajax and encoding, decoding the path. What do you think you gain from it? Security? No. One can figure out that this is bas64 encoded or he just monitors the network traffic and reads the response from the Ajax call.
Just do
embedSwf("flashgame","<? =$path['location']?>"),"<?=$path['base_directory']?>","800","600" )
Really, you cannot prevent someone else seeing the data and are just making things more complicated for you.
(Or you have to decrypt the data with JavaScript.)
(original answer is still correct nevertheless)
Ajax is asynchronous so something like var test = decode(s); will never work. The decode function will return before the Ajax call finishes.
Instead, put your logic into the callback handler. For example, if your code was this before:
var retdata = decode('s');
// here comes code that handles retdata
put the code into a function and call it from the success handler:
function process(retdata) {
// here comes code that handles retdata
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
process(newmsg);
}
});
}
This seems to be a very common problem to all beginners. You will find a lot of questions here that deal with the same problem.
Update:
It is not nice, but you could change the function to
function decode(s, cb){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(data){
cb(data);
}
});
}
and do
decode("<?=base64_encode($path['location'])?>", function(location) {
decode("<?=base64_encode($path['base_directory'])?>", function(dir) {
embedSwf("flashgame",location,dir,"800","600" );
});
});
Update 2:
For completeness, you can make the Ajax call synchronous, by using async: false. Then this will work:
function decode(s){
var ret;
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
async: false,
success:function(newmsg){
ret = newmsg;
}
});
return sync;
}
var val = decode(s);
However, this will block the browser until the Ajax call finished. You have to test whether this matters in your case or not.
Update 3:
You could also change your PHP script to not only accept one parameter but several and process both strings in one go.