8

I have jQuery code that runs fine when a view is render. However, I want this same code to run after an Ajax request is successful. The jQuery was originally performed when the document was ready, but I moved it to it's own function so it can be called. The function adds a few simple classes to some label elements. Here is what I have so far:

$(function () {
    afterLoad();
});

$.ajaxSetup({
    success: function () {
        afterLoad();
    }
});

function afterLoad() {
    // code to execute
}

This doesn't execute properly after making a simple Ajax request:

$('#ajaxTest').load('<MVC Route>')

A partial view is returned just fine, but afterLoad() attempts to run before the partial view is in the DOM. If I were to execute the same call again afterLoad() does run (on the previous partial view), but then it gets overwritten by the new partial view.

Any thoughts? Another approach to this would be fine, I'm looking for a was to get the site-level .js file to run after an Ajax request for a partial view. The master page loads the site.js file, and I would like to execute it's code without reloading the file (since it's already been loaded by the browser). Also, I don't want to have to force developers to do anything different with their Ajax calls so it needs to work with a simple .load(), etc.

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
Brandon
  • 779
  • 5
  • 9
  • 28

7 Answers7

16

This is what I use for what your trying to do:

You also have access to the XHR object should you need to access it.

//Global Ajax Complete
$("body").bind("ajaxSend", function(e, xhr, settings){
    //Sent
}).bind("ajaxComplete", function(e, xhr, settings){
    //Complete
}).bind("ajaxError", function(e, xhr, settings, thrownError){
    //Error
});

EDIT: This is the structure I have, which has been working for me.

site.js

function afterLoad() {
    // code to execute
}
$(document).ready(function(){
    $("body").bind("ajaxComplete", function(e, xhr, settings){
           afterLoad();
    });
});

Created a quick fiddle. is this what you mean?

Edit Two:

You might want to have a listener on the DOM for any <form> element that appears then run your afterLoad() function. This might be a performance hog so I would use it cautiously.

I use livequery to do this

$('form').livequery(function(){
    afterLoad();
});
vinczemarton
  • 7,756
  • 6
  • 54
  • 86
Amin Eshaq
  • 4,034
  • 1
  • 17
  • 21
  • This unfortunately isn't execute anything for me when I put `afterLoad();` in the `ajaxComplete` binding. – Brandon Aug 11 '11 at 18:31
  • is it not stepping into that complete function at all? Do you have the bindings inside $(document).ready()? I'm assuming the afterLoad function is defined before the ajax completes. – Amin Eshaq Aug 11 '11 at 18:36
  • Correct, and it is not hitting `afterLoad()` at all. I have a break point in the function in Chrome which hits whenever a full view is loaded, and in the case I mentioned in the post. There is nothing else in the `$(document).ready()`. – Brandon Aug 11 '11 at 18:41
  • hmm.. interesting...i updated the answer with a quick fiddle. Maybe I'm not understanding – Amin Eshaq Aug 11 '11 at 19:00
  • I have a simple jQuery function that finds required input fields on a form, then finds the associated label and adds a CSS class so the required fields will stand out to the user. In the site.js file this works just fine on every page. However, if the user clicks a button that opens up a popup through Ajax with another form on it, the site.js is not reloaded (as desired) from the partial view, but I still want the function to add the class to the required labels. There are other uses this will help with too, such as loading knockout functions after an Ajax request. – Brandon Aug 11 '11 at 19:08
  • Did another update to the answer. I came across a same problem with styling of table rows that are updated via ajax and i ended up using a listener for the element to appear in the DOM – Amin Eshaq Aug 11 '11 at 19:19
  • That gets me an error: `Uncaught TypeError: Object [object Object] has no method 'livequery'`. – Brandon Aug 11 '11 at 19:29
  • Live query is a plugin, the link is in the post. – Amin Eshaq Aug 11 '11 at 19:30
  • Leave it to me to not notice the blue underlined text. :P – Brandon Aug 11 '11 at 19:34
  • great solution posted – Shoeb Nov 20 '13 at 12:39
  • only working for "/clients/profile?id=1" this types of url i mean edit but other url type not working for me.. any solution plz – Rahul Pawar Jun 17 '16 at 06:46
4

You can set global AJAX defaults in jQuery

like this

$.ajaxComplete(function(){
       afterLoad();
    });

so your method will be executed when ajaxCompleted

Senad Meškin
  • 13,597
  • 4
  • 37
  • 55
1

This works fine for me:

$( document ).ajaxComplete(function( event,request, settings ) {
  //your code here to run when ajax is complete
  alert("Complete");
});
Mike
  • 1,258
  • 12
  • 12
  • Mike, how can you make this work properly in the following scenario?: There are a list of tasks loaded on the page on initial page load and I want some js code to call on them if users click on the task ,so I use $(document)ready + on(click..). On the top of this user can create and append new tasks via AJAX. By default the document ready js doesn't work on the freshly appended tasks. What should I do to have the code qorking on the new tasks as well? My problem is that the functions are exactly the same like in case of doc.ready, but if I simply add them again some events will fire twice. – Sean Magyar Jan 09 '16 at 23:51
  • Mike, pls check my previous comment out too. I got some answers from another user to my question here: http://stackoverflow.com/questions/34664701/firing-js-in-rails-after-ajax-with-no-turbolinks, but I'm not sure if this $container solution is the good approach.I guess there should be some solution with page:change or something like that. – Sean Magyar Jan 09 '16 at 23:53
0

Above answers didn't worked for me. I wasted a lot of time to figure it out, all in vain. Finally I got a solution that works though in a bit unusual way. Here it is. Basically I am reassigning the event handlers after appending the DOM elements from AJAX

function autoLoad(){
//write event handlers which you are again going to assign to the ajax appended     dom elements
}

$(document).ready(function(){
autoLoad;
//more event handlers if present (non dynamic DOM elements)
//Any other Jquery stuff
});

$.ajax({    
//send request here
}).done(function(html) {
//unbind the event handlers assigned in autoload function
append ajax results here
autoLoad();
}).fail(function(ts) {
});
0

If I'm reading your question right, the issue is that you're attempting to issue 'afterLoad' after the ajax call, but before the partial view elements are added to the DOM. In that case, I think you need to call afterLoad as a part of the ajax load method:

$('#ajaxTest').load('<MVC Route>', null, 
    function (responseText, textStatus, XMLHttpRequest) 
    { 
        afterLoad(); 
    });

If I'm off base, let me know, happy coding!

Justin Beckwith
  • 7,686
  • 1
  • 33
  • 55
  • The was off base... it IS executing after the Ajax call and before the partial view is in the DOM. I want it to wait until they're in the DOM so they're affected. :) – Brandon Aug 11 '11 at 18:32
0

Remove the ajaxSetup part.

$.ajaxSetup({
/*  success: function () {
     afterLoad();
  }*/
});

And then use load like this:

$('#ajaxTest').load('<MVC Route>', function(){
       afterLoad();
    });

As per the docs, this should work.

Mrchief
  • 75,126
  • 20
  • 142
  • 189
  • According to the [docs](http://api.jquery.com/load/). `.load` should work for you. But I see another comment where you mention it not working. Is your call coming back successfully? – Mrchief Aug 11 '11 at 18:50
  • Yes, the call is always returning the partial view; the `.load()` works just fine. I'm just trying to find a way to run jQuery that's already been loaded by the parent view once the partial view enters the DOM. – Brandon Aug 11 '11 at 18:53
  • @Brandon: Do you still have the `ajaxSetup` code in place? Remove that and try my update. – Mrchief Aug 11 '11 at 18:54
  • This does work, of course. The only problem is, I'm trying to find a way where the developer's using the framework I'm working on aren't required to know "Hey, whenever I make an Ajax call, I need to call this function as well." I'm looking to make this automatic. – Brandon Aug 11 '11 at 18:57
  • See your actual requirement is "not on ajax complete" but on "dom load after ajax complete". The former can be handled with `.ajaxComplete`. The later, no such builtin function in jQuery. – Mrchief Aug 11 '11 at 19:08
  • Actually, it works on the ajaxComplete built in to jQuery, see the accepted answer above. – Brandon Aug 11 '11 at 19:14
0

The culprit is this

$.ajaxSetup({
  success: function () {
     afterLoad();
  }
});

load internally uses $.get to fetch the data and when it calls the success handler afterLoad method is called before even setting the data into the element. You might have to go with some other approach this will not work.

Try this

    $.ajaxSetup({
      complete: function () {
         afterLoad();
      }
    });
ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124