JQuery $(this) not accessible after ajax POST? - javascript

Let's say I have a bunch of links that share a click event:
Click me
Click me
Click me
Click me
and in the $('.do-stuff').click function I execute a JQuery ajax POST request that updates the database with stuff and I get a successful response. After the ajax is completed, I simply want to change the value of the link text to be whatever I send back from the server...
$('.do-stuff').click(function () {
$.ajax({
type: "POST",
url: "MyWebService.asmx/DoSomething",
data: '{CurrentLinkText: "'+ $(this).text() +'"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
$(this).text(result.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
});
This invoked just fine and I verified that "result.d" is indeed the text from the server but the text is not changing. I think that the $(this) element is no longer accessible after the AJAX post? What can I do to work around this?

In general when you lose context like that, you can save a reference to the object. Like this:
function clickHandler() {
var that = this;
$.ajax( { url: '#',
success: function (result) {
$(that).text(result.d);
}
);
}

See here:
$(this) inside of AJAX success not working
You can set the context option:
This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). (...)
Example:
$.ajax({
//...
context: this,
success: function(json) {
//...
}
});
or use $.proxy:
$.ajax({
//...
success: $.proxy(function(json) {
//...
}, this)
});

Try:
success: $.proxy(function(result) {
//...
}, this)

There are lots of ways to do this, as you can see from the answers here. Personally, I prefer to construct a function bound to the current value of this:
success: (function(target) {
return function(result) {
$(target).text(result.d);
}
})(this)
It's neat, clean, and $(this) will remain the same as it is in the outer context; i.e. it will be the element that raised the event.

jQuery('#youridvalue').html(result.d);
jQuery('.yourclassvalue').html(result.d);
Use it

Related

How to prevent Multiple Ajax request?

I have spent 2 days to find a solution, but stackoverflow does not have correct answer for this.
I have 2 ajax function first loading values onload,
$.ajax({
url: 'http://localhost/movies/data/home_data.php',
type: 'POST',
dataType: 'json',
cache: false,
success: function(data) {
var home_contents_data='';
$.each(data, function(index, element) {
home_contents_data += 'More Details';
});
}
});
it is working and giving data perfectly. it have a onclick function call as "readSingleMovie2()" I want to send this value to another ajax function. this is my second ajax function
//second function
function readSingleMovie2(movie_id2)
{
myApp.onPageInit('single-movie-2', function (page) {
var single_movie_details2 = '';
$.ajax({
url: 'http://localhost/movies/data/single_movie-2.php?rand='+(Math.random()),
type: 'POST',
data: 'movie_id2='+movie_id2,
dataType: 'json',
cache: false,
success: function(data) {
var single_movie_data='';
$.each(data, function(index, element) {
single_movie_data += '<div>'+data[index].film_name+'</div>';
});
}
});
})
}
That is also working perfectly and that function data comes inside to the function.
but my problem is. when I click second time some of value from 1st function. second function's URL loading multiple times.
I have attached firebug screenshot image to get an idea.
I tried with unbind, preventDefault, preventStop and cache false... everything I know and get the internet. But I am still finding the better solution for this.
Please help me to resolve this problem.
Really appreciate your valuable time and answers
Thanks!
Instead of unbind, preventDefault and preventStop, try off() .
See this: http://api.jquery.com/off/

jQuery: using $(this) inside of $.ajax success function

I'm making an $.ajax call, and the following code does not work as intended. The alert results in 'undefined'
$(document).ready( function {
$(".elem").on("click", function(e) {
e.preventDefault();
$.ajax( {
url: 'index.php',
data: {
'action': 'something'
},
success: function() {
alert($(this).data("foobar"));
}
});
});
)};
However, I was able to get it working by adding an alias to $(this) before entering the ajax function.
$(document).ready( function {
$(".elem").on("click", function(e) {
var old_this = $(this);
e.preventDefault();
$.ajax( {
url: 'index.php',
data: {
'action': 'something'
},
success: function() {
alert(old_this.data("foobar"));
}
});
});
)};
I can't assign unique IDs to the element being clicked, so accessing it via $("#id") isn't an option.
Is there a more standardized approach to accessing the $(this) that existed before entering the success function or does this way work just fine?
The way that you have it is just fine. By default this in jQuery ajax callbacks is the ajax settings object (you can set via $.ajaxSettings). $.ajax also has a context property that you can set:
$.ajax({
url: url,
data: data,
context: this,
success: success
});
Then you could use $(this) as expected, but personally I find the reassignment of this easier to understand. You may want to pick a better variable name than old_this, though.

Can't access object made by ajax call

I have this ajax request:
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
});
as you can see it makes new row in #table. But this new objects made by ajax are not accessible from next functions. Result from ajax is not a regullar part of DOM, or what is the reason for this strange behavior?
$('#uid').on('click', function () {
alert('ok');
});
Use event delegation:
$(document).on('click','#uid', function () {
alert('ok');
});
Note that ajax calls are asynchronous. So whatever you do with the data you need to do it in a callback within the success function (that is the callback which is called when the ajax call returns successfully).
Jquery on doesn't work like that. Use have to give a parent which not loaded by ajax, and the specify ajax load element like this
$('#table').on('click','#uid' ,function () {
// what ever code you like
});
Is simple and complex at the same time. Simple to solve but complex if you are getting started with javascript...
Your event handler - onclick is being fired and bound to an object that doesnt yet exist.
So when you append the object to the #table, you need to set up your click handler as the object now exists.
So in your success part of the ajax return add the click handler event there.
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
Or how about you make it dynamic and create a function to do it for you.
function bindClick(id) {
$('#' + id).click(function() {
//Do stuff here
console.log('I made it here' + id);
});
}
Then:
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
bindClick(uid);
});
}
This is a super contrived example but you get the idea you just need to make the rest of it dynamic as well. for example some name and counter generated id number: id1, id2, id3...
Try it like this, add this $('#uid').on('click', function () { into the success
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
});

Callback failing if contains ajax

I'm trying to add a callback to a pre existing function in the jquery plugin nitelite https://github.com/premasagar/nitelite - The callback works fine http://jsfiddle.net/HPc4e/2/ - unless I have ajax in the callback?
Appropriate section of close function:
// Blah blah ...
else {
showFlash();
this.overlay.remove();
this.container
.empty()
.remove();
$(this).triggerHandler('close');
// Add callback
if (typeof callback == "function") {
callback();
}
}
return this;
Callback:
lb.close(undefined, 'click', function() {
$.ajax({
type: 'POST',
url: url,
data: {submit: $(this).val()},
dataType: 'json',
success: function(data) {
lightbox('Lightbox 2', '<p>Oh hi</p>', 'lightbox2');
}
});
});
Thanks
I suspect that your callback is throwing an exception.
What is the value of this supposed to be when it's invoked? Are you sure it's pointing at a jQuery compatible element that has a .val() method?

What is the easiest/best way to show that an HTML element is AJAX Loading?

Sometimes in my application there are many elements loading so I want to show the typical AJAX spinner above the control (or DOM node) with it disabled.
What is the easiest/best way to do that?
Ideally I would like to:
$("#myelement").loading();
$("#myelement").finishloading();
Or even better being able to do AJAX requests directly with the element:
$("#myelement").post(url, params, myfunction);
Being #myelement a regular node or form input.
You could use beforeSend and complete callbacks:
$.ajax({
url: 'script.cgi',
type: 'POST',
beforeSend: function() {
$('.spinner').show();
},
complete: function() {
// will trigger even if request fails
$('.spinner').hide();
},
success: function(result) {
// todo: do something with the result
}
});
Since you're already using jQuery, you may want to look into BlockUI in conjunction with Darin Dimitrov's answer. I haven't used it yet myself as I just came across this today, but it looks decent.
If you're writing a semi-large-ish application and anticipate making many AJAX calls from different places in your code, I would suggest that you either add a layer of abstraction over $.ajax, or create a helper function to avoid having boiler plate for your UI indicator all over the place. This will help you out a lot should you ever need to change your indicator.
Abstraction method
var ajax = function(options) {
$.ajax($.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
));
};
ajax({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
});
Helper method
var ajaxSettings = function(options) {
return $.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
);
};
$.ajax(ajaxSettings({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
}
}));
Also, I wouldn't suggest overwriting the $.ajax method itself.
what i've done in the past is, on post pass the element id (a containing div) to a function which replaces it's inner HTML with a loading image, and then in the post back replace it's content again with the updated real content.
If you want to show the spinner every when an ajax call is in progress I think you should use ajaxStart and ajaxStop.
$("#spinner")
.ajaxStart(function(){$(this).show();})
.ajaxStop(function(){$(this).hide();});

Categories