I am new to both Django and Javascript and am having trouble calling a user defined function from within a javascript function in Django template.
I have a javascript block as follows:
function EditDialog(pk) {
$.ajax({
url: "{% url 'populatereviewform' %}",
method: 'GET',
data: {
pk: pk
},
success: function(formHtml){
//Do something
alert("Success!")
},
dataType: 'html'
});
// this is my function that I would like to call
function MyFunc(e, offset) {
alert("Calling my function")
}
// Now I try to call this function from another function
("#dialog").submit(function(e)
{
this.MyFunc(e, "1");
return false;
});
}
My question is how can I call this nested function?
In the code above, I am creating a function called MyFunc which I am trying to call from the submit method. However, this comes back with this.MyFunc is not a function.
The this is bound to something else.
Remove this and call your function like this: MyFunc().
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
im trying to assign a variable inside the ajax success callback.
i know that in order to assign the value i need to use a call back function. but i want that function to be inside the class. is it possible to implement something like this?
function callMgmt_class() {
this.room_id = 'Error';
this.assignRoomVar = function(room_id) {
alert();
this.room_id = room_id;
}
this.getRoomID = function() {
$.ajax({
url: "/get_room_id.php",
dataType: "json",
success: function(data) {
this.assignRoomVar(data.room_id);
}
})
}
}
is there some way to use bind?
i tried:
success: function(data) {
(function() { this.assignRoomVar(data.room_id); }).bind(this);
}
so i dont get any errors but the function does not seem to be called.
Your use of this is flawed. 'this' inside the callback will use the context of the callback whereas what you need is the context of your class. You can do that by caching the 'this' context in a variable and using it instead.
this.getRoomID = function() {
var me = this;
$.ajax({
url: "/get_room_id.php",
dataType: "json",
success: function(data) {
me.assignRoomVar(data.room_id);
}
})
}
this is not the this you are looking for.
The this keyword is tricky and takes on different references depending on the context. When you are accessing this in the ajax success function, it is not referring to the callMgmt_class object anymore (I think it would reference the ajax function).
The best way to get around this is to assign this to another variable when you are sure of its value. So at the beggining of your function is the best bet
this.getRoomID = function() {
var that= this;
//Now use that instead of this when you want to refer to the callMgmt_class object
$.ajax({
url: "/get_room_id.php",
dataType: "json",
success: function(data) {
that.assignRoomVar(data.room_id);
}
})
}
Addition:
I think using bind or apply are other alternatives, but I am not very familiar, so I'll leave that for someone else to answer.
I have the problem that I want different callback routes for the same AJAX request because sometime it's necessary to use the same function (i.e. getting information about product ID or something similar).
What works is something like this:
function1() {
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
route1function();
});
}
function2() {
$.ajax({
url: "test.html", // do the same crap here...
context: document.body
}).done(function() {
route2function();
});
}
function3() {
$.ajax({
url: "test.html", // and here again *yawn*
context: document.body
}).done(function() {
route3function();
});
}
Copy & Paste coding is evil, so my idea was to do something like:
doMyAmazingStuff(iRoute) {
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
switch(iRoute) {
case 1:
route1function(data);
break;
case 2:
route2function(data);
break;
// and so on...
}
});
}
Unfortunately, iRoute will NOT be passed to the .done function and is undefined. Any alternatives how to survive such variables? Copy / paste / paste / paste ... like in the first example is no option (and bad style as well). And making them global scoped (setting a shadow variable without declaring it with var) isn't a that good solution, I think.
First, your statement "iRoute will NOT be passed to the .done function and is undefined" is incorrect. If you pass in iRoute to your function it will not be undefined. See this demonstration. I'm passing in 1 as an argument to the function and the alert within the done function is alerting that number.
There might be a tidier way of writing that code, but it's pretty much the same code - it just means using the AJAX promise interface to return the data from a separate function instead.
function getData() {
return $.ajax({
url: "test.html",
context: document.body
});
}
function doMyAmazingStuff(iRoute) {
getData.done(function (data) {
switch(iRoute) {
case 1:
route1function(data);
break;
case 2:
route2function(data);
break;
}
});
}
doMyAmazingStuff(1);
I have this:
var myapp;
function Menu($scope){
$.ajax({
url: "/user.php",
type: "POST",
success: function(data){
}
});
}
How do I use the data out of the function scope?
You're having trouble because the ajax operation is asynchronous. This means that, after $.ajax is called, you can't control when exactly the response will arrive. In the mean time, your code keeps running normally, and if you try to use the response before it arrives, it will be empty.
You say in the comments that a framework calls your Menu function, so I'm assuming you can't control what parameters are passed to it. In this case, you should only use the data inside the success callback:
function Menu($scope){
$.ajax({
url: "/user.php",
type: "POST",
success: function(data){
// USE data HERE
}
});
}
In case you can modify how Menu is called, you can pass a callback function to it, and let that manipulate the results:
function Menu($scope, ajaxCallback){
$.ajax({
url: "/user.php",
type: "POST",
success: ajaxCallback
});
}
// Define the callback where you will use the data
function processData(data) {
// USE data HERE
}
// Call Menu passing the callback
Menu(whateverScopeIs, processData);
You can create a variable at the scope you need, and save the data to that variable. Or you can call a function and pass that data to it.
For example:
function alertData(data){
alert(data); // I can use the data here now!
}
var foo;
$.ajax({
url: "/user.php",
type: "POST",
success: function(data){
alertData(data);
}
});
}
Create a global variable, assign data to it, and then use the global variable.
e.g.
var foo;
function bar(baz) {
foo = baz;
}
bar("test");
alert(foo);
I'm having serious problems with the function below:
function requestUploadedSearch()
{
var cookie = JSON.parse(readCookie("user_search_cookie"));
$.ajax({
dataType: "script",
async: false,
data: {
context: "search-get",
code: removeNull(cookie, cookie !== null, "code")
},
success: function(data)
{
var keywords = search_return["keywords"];
return keywords; // here is the damn problem.
}
});
}
Seams that simply nothing comes out of the function except for the undefined value and no errors are shown in the debugger.
And I'm seriously almost throwing my laptop on the wall.
If anyone could help me doing this, please answer!
Thanks in advance.
1st off: Where is the search_return variable? Why are you ignoring data?
I have a feeling this is what you want to do:
function requestUploadedSearch()
{
var cookie = JSON.parse(readCookie("user_search_cookie"));
var keywords;
$.ajax({
dataType: "json",
async: false,
data: {
context: "search-get",
code: removeNull(cookie, cookie !== null, "code")
},
success: function(data)
{
keywords = data["keywords"];
}
});
return keywords;
}
The issue is that since the Ajax call will complete at an arbitrary time in the future, you cannot simply return a value from its success handler.
One issue is that you're not actually doing anything with the data returned by the server, which seems puzzling.
The nutshell version is that you need to implement the functionality as part of the success callback. That can be done in-line, or you can create the callback function outside of the Ajax call itself and use it as the value for the success property:
function onSuccess(data) {
// Do something with the data here
}
...
$.ajax({ // etc.
success: onSuccess
};
You may also use jQuery's $.when function.
The problem is the scope you're trying to return your keywords from. The success function is called by jQuery, and you don't have any control over what jQuery does with that return value. You could do return $.ajax(... but you wouldn't get what you expect, since according to the documentation: "As of jQuery 1.5, the $.ajax() method returns the jqXHR object, which is a superset of the XMLHTTPRequest object" (http://api.jquery.com/Types/#jqXHR).
What you should do instead is set up a callback function like:
function doSomethingWithKeywords(keywords) {
// do stuff
};
and in the success function call that function:
doSomethingWithKeywords(keywords);
EDIT: Hogan's is a good solution, since your call isn't asynchronous.
The problem you are having is the return you are passing is not the return of the function -- it is the return of the event of success. Often closures (implied passing of a local variable to a function) are used to solve this problem in JavaScript.
NB I still don't think your function will work because I don't see where search_return["keywords"] is defined. But at least you won't have to worry about the closure issue. Once your success function is correct the main function will return it.
Like this:
function requestUploadedSearch()
{
var cookie = JSON.parse(readCookie("user_search_cookie"));
var returnClosure;
$.ajax({
dataType: "script",
async: false,
data: {
context: "search-get",
code: removeNull(cookie, cookie !== null, "code")
},
success: function(data)
{
// returnClosure = data["keywords"];
returnClosure = search_return["keywords"];
}
});
return returnClosure;
}
I have this ajax call to a doop.php.
function doop(){
var old = $(this).siblings('.old').html();
var new = $(this).siblings('.new').val();
$.ajax({
url: 'doop.php',
type: 'POST',
data: 'before=' + old + '&after=' + new,
success: function(resp) {
if(resp == 1) {
$(this).siblings('.old').html(new);
}
}
});
return false;
}
My problem is that the $(this).siblings('.old').html(new); line isn't doing what it's supposed to do.
thanks..
all helpful comments/answers are voted up.
Update: it appears that half of the problem was the scope (thanks for the answers that helped me clarify that), but the other half is that I'm trying to use ajax in a synchronous manner. I've created a new post
You should use the context setting as in http://api.jquery.com/jQuery.ajax/
function doop(){
var old = $(this).siblings('.old').html();
var newValue = $(this).siblings('.new').val();
$.ajax({
url: 'doop.php',
type: 'POST',
context: this,
data: 'before=' + old + '&after=' + newValue,
success: function(resp) {
if(resp == 1) {
$(this).siblings('.old').html(newValue);
}
}
});
return false;
}
"this" will be transfer to the success scope and will act as expected.
First of all new is a reserved word. You need to rename that variable.
To answer your question, Yes, you need to save this in a variable outside the success callback, and reference it inside your success handler code:
var that = this;
$.ajax({
// ...
success: function(resp) {
if(resp == 1) {
$(that).siblings('.old').html($new);
}
}
})
This is called a closure.
this is bound to the object to which the executing function was applied. That could be some AJAX response object, or the global object (window), or something else (depending on the implementation of $.ajax.
Do I need to capture $(this) into a variable before entering the $.ajax call, and then pass it as a parameter to the $.ajax call? or do I need to pass it to the anonymous success function? If that's going to solve the problem, where do I pass it to the $.ajax?
You do indeed need a way to capture the value of this before defining the success function. Creating a closure is the way to do this. You need to define a separate variable (e.g. self):
function doop() {
var old = $(this).siblings('.old').html();
var new = $(this).siblings('.new').val();
var self = this;
$.ajax({
url: 'doop.php',
type: 'POST',
data: 'before=' + old + '&after=' + new,
success: function(resp) {
if(resp == 1) {
$(self).siblings('.old').html(new);
}
}
});
return false;
}
The success function will retain the value of self when invoked, and should behave as you expected.