I have the following situation: page displays set of items, when user clicks on item, item details loaded through ajax request. What I want to do is to prevent ajax requests on further clicks, because information is already loaded.
I use jQuery and Rails 3 and my code looks something like this:
# view
- @items.each do |item|
.item
= link_to item.name, item_path(item), :remote => true
// js
$(function(){
$('.item').bind('ajax:success', function(xhr, data, status){
...
});
$('.item').bind('ajax:before', function(xhr){
if (...) { // check if data already loaded
// ???
}
});
});
Am I on a right way? Or there is another solution?
You can set a flag like itemsLoaded = false
before ajax call. The moment the detail is loaded you can set that flag to itemsLoaded = true
. The ajax call should only be performed when if(!itemsLoaded){/* Do ajax to fetch details */}else return;
I think the only thing you can do is to ensure that the click in the item only goes to the ajax function once. Ways to do this:
The click event invokes a function that disables the binding of the item
If you want to be sure, you do the same in the ajax success function
After clicking the item, your function checks if the item info is already there. If it is, then it just returns.
One solution is you could create a boolean value then only make the ajax call if that value is false.
Set a variable in the Ajax:success function like so...
AjaxSuccessVar=0;
$(function(){
$('.item').bind('ajax:success', function(xhr, data, status){
AjaxSuccessVar = 1;
});
$('.item').bind('ajax:before', function(xhr){
if (AjaxSuccessVar==0) { // check if data already loaded
//then do your ajax function here
}
});
How about using a .data
property as an indicator, e.g.:
$('.item').bind('ajax:success', function(xhr, data, status){
$(this).data("loaded", true);
}).bind('ajax:before', function(xhr){
if (!$(this).data("loaded")) {
// data has not been loaded
} else {
// do something
}
});
EDIT:
Try unbinding the click handler from the item 'trigger' once it has been clicked, e.g.:
$(".item").click(function() {
$.ajax({ ... });
$(this).unbind("click");
});
or perhaps upon successful completion of the request ajax:success
$('.item').bind('ajax:success', function(xhr, data, status){
$(this).unbind("click");
});
It turned out that I used wrong callback. The right callback is ajax:beforeSend
with the following signature function(event, xhr, settings)
. To prevent request sending I used xhr.abort()
and it works fine.
http://www.alfajango.com/blog/rails-3-remote-links-and-forms/