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.

7 Answers 7

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();
});
Sign up to request clarification or add additional context in comments.

11 Comments

This unfortunately isn't execute anything for me when I put afterLoad(); in the ajaxComplete binding.
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.
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().
hmm.. interesting...i updated the answer with a quick fiddle. Maybe I'm not understanding
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.
|
4

You can set global AJAX defaults in jQuery

like this

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

so your method will be executed when ajaxCompleted

2 Comments

that gives me the error: Uncaught TypeError: Object function (a,b){return new d.fn.init(a,b,g)} has no method 'ajaxComplete'.
@Brandon so do $(document).ajaxComplete(function(){
1

This works fine for me:

$( document ).ajaxComplete(function( event,request, settings ) {
  //your code here to run when ajax is complete
  alert("Complete");
});

2 Comments

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.
Mike, pls check my previous comment out too. I got some answers from another user to my question here: stackoverflow.com/questions/34664701/…, 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.
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!

1 Comment

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. :)
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();
      }
    });

3 Comments

What other options do I have to globally handle running a function after the fetched data is entered into the DOM?
Try to use the complete callback, check my edited answer, thanks.
I didn't mention it in the OP but I tried this; using complete doesn't trigger afterLoad() at all. I thought that was odd.
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.

6 Comments

According to the docs. .load should work for you. But I see another comment where you mention it not working. Is your call coming back successfully?
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: Do you still have the ajaxSetup code in place? Remove that and try my update.
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.
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.
|
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) {
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.