How to call a method of a javascript object inside ajax - javascript

Given this code,
var submit = {
send:function (form_id) {
var url = $(form_id).attr("action");
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
this.ret(result.message);
},
error: function(result) {
// Some error message
}
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
will send a data from the form to a controller which if will return a json
$result['message'] = validation_errors();
echo json_encode($result);
I try to call this javascript object in this code,
var res = submit.send(form_id);
wherein form_id is the form id, and look for the output using
console.log(res);
In the console, it shows undefined. After searching for an explaination using google and stackoverflow itself I got the idea that,
this.ret(result.message);
is being called inside ajax which is another object, indicating that it's not part of it's method.
My problem is, how to call the method ret() inside ajax?
Is anyone can explain it to me?

There is several ways to deal with it.
One is ES5 compatible (and this is actually quite common pattern):
var submit = {
send: function (form_id) {
var url = $(form_id).attr("action");
var self = this; // << this is binded to self varialble
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
self.ret(result.message); // << replaced this to self so it has all the methods from the submit object.
},
error: function(result) {
// Some error message
}
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
And another is using arrow function from ES2015 plus deferred object returned by $.ajax:
var submit = {
send: function (form_id) {
var url = $(form_id).attr("action");
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json'
})
.then((result) => {
this.ret(result.message); // << arrow function is called in context of the parent function, so no needs to change anything.
})
.fail(function(result) {
// Some error message
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
Explanation: context of this in callback function will be bind to global scope not to the object's one. So you need somehow to change it.
You can actually match and mix these two methods.
You can also use bind or put success as a object method. As it mentioned in other answers. Same thing, you want to keep this to be object's context.
There is a good article about this in javascript.

You've two options.
1. The "bind()" method (recommended)
The method bind is for changing the context of a function. From the docs:
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
Here the bind will change the context of success function with the reference of this i.e. the submit.
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
this.ret(result.message);
}.bind(this), // <== bind method
error: function(result) {
// Some error message
}
});
That .bind(this) can also be written as .bind(submit);
2. Using the scope variable
Since you already have access to the submit variable, why not directly call with submit instead of this
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
submit.ret(result.message);
}.bind(this),
error: function(result) {
// Some error message
}
});

success: function(result) {
this.ret(result.message);
}
In the above block the this refers to the function you are operating in.
To use ret method you should use it submit.ret.

I have a small code fragment, that simulates this:
var submit = {
send:function (form_id) {
var self = this;
setTimeout(function()
{
console.log('send', this);
self.ret('message'); //will do
//submit.ret('message'); //will do
//this.ret('message'); this.ret is not a function
//ret('message'); ret is not defined
}, 0);
},
ret:function (result) {
console.log('ret', result, this)
this.result_data = result;
},
result_data:""
};
There you can see your possible choices to handle this.
Or use this fiddle: https://jsfiddle.net/syqjwk2q/#&togetherjs=mpwEnNDeIJ

In the submit define
self = this
And then use ret() with self: self.ret()

Related

How to pass a variable from ajax to nested ajax

I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});

jquery: function parameter is undefined in success callback

I am trying to access graphList within success callback, but graphList is undefined. I referred this StackOverflow post. However, I am not able to access elem. Any help would be appreciated.
getGraphData = function (graphList) {
$.ajax({
type: "GET",
url: 'someURL',
beforeSend: function(xhr){},
success: function(result) {
console.log(result);
console.log(graphList);//undefined
}
});
}
Added creating getGraphList function as below, I can access getGraphList inside success callback
var graphList;
var promise = graphInit(response);
promise.done(function(data){
getGraphData(data.graphs)
}
graphInit = function(response,graphList){
getGraphList = function(){return response.graphs;}
}
getGraphData = function (graphList) {
$.ajax({
type: "GET",
url: 'someURL',
beforeSend: function(xhr){},
success: function(result) {
console.log(result);
console.log(graphList);//undefined
graphList = getGraphList();//available
}
});
}

javascript updating hidden value

I have a function:
function add() {
$.ajax({
type: "POST",
url: "add.php",
async: "false", // Tried both- async: "false/true"
data: {
name: 'Test',
},
success: function(data) {
document.getElementById('id').value = data;
id = document.getElementById('id').value;
alert(id); // alerts here proper value
}
});
}
function testMyFunction() {
add();
// 'id' was set in add function.
id = document.getElementById('id').value;
alert(id); // Here does not alert value but blank(no value)
// This 'id' value is used at other place but here is issue.
}
Calling testMyFunction() function gives above mentioned issue.
What could be a issue?
$.ajax is an asynchronous call and it updates "id" field after if it is completed. Your code checks for its value in function testMyFunction() instantly after the invocation (and before success: function(data) is invoked).
JavaScript is an asynchronous language. In a nutshell, this means that your code should NEVER block: functions should either complete immediately or get called later, i.e. after some input/output operation is complete (e.g. AJAX request).
Edited: BTW, your code does not work because even with async: false the success function is called in the event loop, thus this can occur even after the code that follows synchronous AJAX. If you use async: true, the AJAX will block, but the success function will be called asynchronously in any case.
So to handle data synchronously, you have to work not with success function, but rather with an object that is returned by $.ajax() call:
var xhr = $.ajax({
type: "POST",
async: false,
url: "add.php",
data: {
name: 'Test',
},
});
alert(xhr.responseText); // Alerts result
Thus, you should never use async: false. Instead, better refactor your code to be like this:
function add(callback) {
$.ajax({
type: "POST",
url: "add.php",
data: {
name: 'Test',
},
success: callback
});
}
function testMyFunction() {
add(function(data) {
// This closure will be called AFTER the request is complete.
document.getElementById('id').value = data;
alert(data); // Alerts proper value.
});
}
Basically, this pseudo-code is WRONG:
result1 = action1();
result2 = action2(result1);
result3 = action3(result2);
...and should be written like this:
action1(function(result1) {
action2(result1, function(result2) {
alert(action3(result2));
});
});

jQuery .ajax call never calling method

In this SO post I learned how to get a return value from an AJAX call:
function CallIsDataReady(input) {
$.ajax({
url: "http://www.blah.com/services/TestsService.svc/IsDataReady",
type: "GET",
contentType: "application/json; charset=utf-8",
data: input,
dataType: "json",
success: function (data) {
if (!data) {
setTimeout(function (inputInner) { CallIsDataReady(inputInner); }, 1000);
}
else {
//Continue as data is ready
callUpdateGrid(input);
}
}
});
}
$(document).ready(function () {
var input = { requestGUID: "<%=guid %>" };
CallIsDataReady(input);
});
This function calls its web service wich does return true. The problem is that inside the following callUpdateGrid, the logging shows that that web service method is not getting called from the $.ajax call:
function callUpdateGrid(input) {
console.log(input);
$.ajax({
url: "http://www.blah.com/services/TestsService.svc/GetContactsDataAndCountbyGUID",
type: "GET",
contentType: "application/json; charset=utf-8",
data: input,
dataType: "json",
success: function (data) {
var mtv = $find("<%= RadGrid1.ClientID %>").get_masterTableView();
console.log(data);
mtv.set_dataSource(data.d.Data);
mtv.dataBind();
}
});
}
Anyone know what is wrong?
It is always a good idea to include an error handler function as one of the options passed to $.ajax. For example, add this code after your success functions:
,
error: function(jqXHR, textStatus, errThrown) {
console.log("AJAX call failed");
console.log(errThrown);
}
That will log at least a bit of information if the $.ajax call doesn't succeed.
EDIT
According to your comment, this logs
SyntaxError: Invalid character
And in fact, I now see that you are giving a plain JavaScript object as the data option passed to $.ajax, but indicating that it is a JSON object in the dataType field. You need to actually convert the input object into JSON yourself, like so:
data: JSON.stringify(input),
dataType: 'json',
Alternatively, you could simply format input as a JSON object in first place, like so:
var input = { "requestGUID": "<%=guid %>" };
The quotes around the field name requestGUID are sufficient, in this case, to give you a JSON object.

jQuery Ajax Call function

I want to be able to call a function from the "on success" region instead of having to place my code in that region. I'll be using the code twice so I'm trying to figure out how to place it outside of the jQuery.ajax() function.
Here is my current code:
$.ajax({
type: "GET",
url: "ws/getweather.ashx?zip=" + vZip,
dataType: "xml",
success: function (xml) {
$(xml).find('weather').each(function () {
// Load New Data
...
});
},
error: function (xml) {
alert("Unrecognized Region. Please try again.");
}
});
So instead of having...
function (xml) {
$(xml).find('weather').each(function () {
// Load New Data
...
});
I'd like to put the name of another function, and pass the xml to that function. That way I can have other events call the same set of code.
Thanks in advance!
UPDATE===================================================
Thanks to Mike Richards for his timely response. I'm including the exact syntax below because I had to add a few details to make it work...meaning, pass the XML to the other function.
$.ajax({
type: "GET",
url: "ws/getweather.ashx?zip=32751",
dataType: "xml",
success: function (xml){
weatherize(xml);
},
error: function (xml) {
alert("Unrecognized Region. Please try again.");
}
});
And then somwhere below, my other function
function weatherize(xml) {
$(xml).find('weather').each(function () {
// Load New Data
...
})
};
you can just pass in a function for that parameter :)
success : successFunction,
and then, somehwere else:
function successFunction(data) {
// Do Something
}

Categories