I was wondering how easy is to to expand this code so that it shows an error if it cannot connect and whilst it is connecting it shows a loading text or loading image. It seems pretty standard behaviour on ajax driven sites but I haven't found much useful information online on how to achieve it.
$(document).ready(function () {
var loadUrl = 'http://sheldonbrown.com/web_sample1.html';
$("#close").click(function () {
$("#country_slide").hide();
});
$("#country").click(function () {
$("#country_slide").show();
$("#country_slide").html(ajax_load).load(loadUrl);
});
});
Depending on the context of your application, you can subscribe callbacks to fire on certain global AJAX events. Say, whenever an AJAX call starts, or whenever an AJAX call throws an error.
$(document)
.ajaxStart(function (e) {
$('body').showMyAwesomeLoadingGIF();
})
.ajaxComplete(function (e) {
$('body').hideMyAwesomeLoadingGIF();
});
This will cause those two callback functions to fire during the appropriate lifecycle events on every AJAX call made in your document.
If, for some reason, you want a certain AJAX call not to trigger your global AJAX event handlers, you can specify that that particulat AJAX call is not global.
$.ajax({
global : false,
// blah
})
More information on global AJAX event handling here.
EDIT
If you want to maintain a bit more granular control, there's $.ajaxSetup(), but since jQuery themselves discourages its use, I'm thinking you might be left with having to fashion your own solution.
Personally, I'd use a wrapper function with a closure to set my custom option values if they're something you expect to do repeatedly.
var ajax = (function () {
var defaults = { };
return function (opts) {
opts = $.extend({}, defaults, opts);
// place what you want to happen when an AJAX call starts here
return $.ajax(opts)
// place corresponding events here
.done(function (m) {
})
.fail(function (x,s,e) {
})
.complete(function (m) {
});
};
}());
// then use that in your code like how you'd use $.ajax():
ajax({
url : 'http://my.domain.com/api/users',
type : 'GET'
}).done(function (m) {
console.log('Done GET users.');
});
// ... and you can be sure that it has default options and default event handlers,
// while being able to add on to them if you wish.
Related
I have two functions in jQuery that I want to fire in a specific order. The first function is an ajax function which updates a partial view. The other one is supposed to do some styling on the partial view, once the ajax function has completed - this function takes a parameter.
ajaxFunction();
stylingFunction(params);
I have tried the following:
ajaxFunction(function() {
stylingFunction(params)
});
Also, I have tried to use a callback:
ajaxFunction(stylingfunction(params));
ajaxFunction(callback)
{
//Do update
callback()
}
None of these do however work. The styling appears shortly where after it dissapears because the partial view is getting updated. Where am I going wrong here?
Both functions are written in my "parent" view.
You can use .done() and .fail() chained to the $.ajax call ...
I created a couple callback functions with psuedo-code inside the successCallback() since you said you only need to run the styling function "sometimes". You will want to test whatever condition inside that function to determine if you want to run the styling function. Hope this helps.
(function($) {
$(function() { //document.ready
$.ajax({ cache: false,
url: "/blah/vlah/lah",
data: { somedata: somedata }
})
.done(successCallback)
.fail(failCallback);
});
function successCallback(data) {
if (someCondition) {
stylingFunction(params);
}
};
function failCallback(jqXHR, status, error) {
console.log(jqXHR);
console.log(error);
console.log(status);
};
})(jQuery);
I created another gist which handles ajax event delegation, you may want to review and incorporate anything that seems helpful to your situation.
https://gist.github.com/inceptzero/a753d020648f49da90f8
I also created this gist on github for an ajax request queue which is a bit more elegant and robust.
https://gist.github.com/inceptzero/e64756f9162ca6aeeee5
Since you are using jQuery you could const ajaxFunc = callback => $.ajax({...}).done( data => callback) Also you could use async/await. You can read more about it on MDN.
I have an ASP MVC application that lets a user add multiple partial views to a div with jQuery ajax calls.
jQuery("#AddNew").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
jQuery("#DivId").append(html);
}
});
return false;
});
The problem is that since a user must be authorized for the action returning the partial view, when a user's session has timed out, it is rendering the login page instead of the partial view. I have multiple places that are using similar ajax calls, so I added the following as a global ajaxSuccess event:
jQuery(document).ajaxSuccess(function (event, request, settings) {
var isLogin = jQuery(request.responseText).find('.login-form').length;
if (isLogin > 0) {
var url = document.URL;
var rootPath = '#Request.Url.GetLeftPart(UriPartial.Authority)';
var path = url.replace(rootPath, '');
var pathEncoded = encodeURIComponent(path);
var loginURL = rootPath + "/Account/Login?returnUrl=" + pathEncoded;
location.href = loginURL;
}
});
This works, as it will redirect the user to the login page when an unauthorized ajax request is made. However, it is still adding the html to the div, which is visible for a short time before the redirect.
Is there a way to get the global event to trigger before the local one? The jQuery API shows that the local success event is triggered before the global ajaxSuccess event, so I tried changing the ajax call to use complete, rather than success. This does work, but it seems like if for some reasons I needed to add code in the future that only executes on success, that I'll run into the same problem. Is there a better way to handle this?
I might advise creating your own API wrapping the ajax method which ensures the functionality you desire (in particular, the order of operations). Here's a very over-simplified example:
var async = function(props) {
var finished = $.Deferred();
$.ajax(props)
.done(function(response) {
// detect auth timeout, handle consisently
if(response.isAuthTimeout) {
// render login ui
finished.reject('auth-timeout');
} else {
finished.resolve.apply(finished, arguments);
}
})
.fail(function() {
finished.reject.apply(finished, arguments);
})
return finished;
};
Then, in practice you'll make calls to async (or whatever you decide to call your wrapper) rather than the native $.ajax API.
Make sense?
Pjax will not allow me to specify functions as an option when calling it directly.
$(document).on('click', 'a.inferno-preview', function(event) {
return $.pjax.click(event, {
container: '#preview-overlay',
fragment: '#preview-overlay',
send: function() {
return $('#preview-overlay').removeClass('hidden');
},
complete: function() {}
});
});
In this case, the 'send' and 'complete' functions are not being executed, while 'container' and 'fragment' is working well. Why is this and what do I need to do to make Pjax recognize my functions?
By the way: I can not use the conventional form of using Pjax, I need more control about the happening, so I need to use the $.pjax.click object. Yet it would work fine with the functions in the common way like in the following:
$(document).pjax('a.inferno-preview', '#preview-overlay', {
send: function() { alert('this will work.'); }
});
In pjax send and complete events are not called if a request if retrieved from cache so you will not get your overlay down. Instead use success or complete depending on your particular use case.
I have a application where there are numerous number of ajax calls to the server.
Now I want to audit the response that comes from the server (This requirement poped up after the ajax code was laid).
So I have a function that would audit the response data, only problem is how can I get the data to be sent to the function which now sits separately.
I don't want to do the laborious work of adding the line of code for calling the function in each ajax call.
Is there easier and general way out. Somehow I could detect when a response come back and then process the response.
Using both traditional javascript method as well as jquery ajax calls in the system. (The app has been getting changes from a long time and has changed hands a lot so the new things get added and the older ones never get removed)
Wrap your ajax calls with a helper function and use it throughout your code.
An (untested) example:
MyApp = MyApp || {
logRequest: function _logRequest(settings, response) {
// Log your response
},
ajax: function _ajax (settings) {
var that = this;
// Log attempt request here?
// Example of logging the success callback (do similar for error or complete)
if (settings.success) {
// A success handler is already specified
settings.success = function (data) {
that.logRequest(settings, data); // Log the response
settings.success(data); // Call the original complete handler
};
} else {
// No success handler is specified
settings.success = function (data) {
that.logRequest(settings, data);
};
}
return jQuery.ajax(settings);
}
};
I favour this mechanism for lots situations where I want to reduce boilerplate. I only have to modify the state of the MyApp object which is my own (named appropriately for the application), so it is sort of an interface that allows you to intercept function calls without modifying other global objects. You can also swap this functionality out with something else very easily without having to update your references everywhere, which could be useful in a lot of other situations as well.
Using .ajaxComplete() should be enough to catch the onComplete event for all AJAX requests made through jQuery. Isn´t that what you´re asking for?
$('.ajaxRequest').click(function(event) {
event.preventDefault();
$.getJSON(
'/echo/json/',
this.id,
function(data, textStatus, jqXHR) {
console.log(data, textStatus, jqXHR);
}
);
});
// Listen to all ajax requests
$("#log").ajaxComplete(function(event, request, settings) {
console.log(event, request, settings);
});
View demo.
I have written a function that retrieves a html template, then binds data using jQuery.tmpl. I think it's fairly neat and tidy and encapsulates what I need and provides me a reusable function. My question however is can it be improved.
My main concern is what if the $.get method fails, and also how the callBack function is executed.
function Bind(templateURL, templateData, templateTarget, callBack){
var req = $.get(templateURL);
req.success(function(templateHtml) {
$(templateTarget).html(''); //clear
$(templateHtml).tmpl(templateData).appendTo(templateTarget); //add deal
callBack();
});
}
You can pass the result of tmpl() directly to html() to clear your target container and append the new content at the same time. You can also chain the result of $.get() into your success handler to avoid using a local variable:
function Bind(templateURL, templateData, templateTarget, callBack)
{
$.get(templateURL).success(function(templateHtml) {
$(templateTarget).html($(templateHtml).tmpl(templateData));
callBack();
});
}
If $.get() fails, nothing will happen since you do not register an error handler. What that handler would do is up to you, but you might want to display an appropriate message in an alert box or somewhere on the page.
Your second concern is less clear. As it stands, callBack will only be called on success, and without arguments.
You can use $.ajax to assign and error calback. ex:
var jqxhr = $.ajax({ url: "example.php" })
.success(function() { alert("success"); })
.error(function() { alert("error"); })
Check the api http://api.jquery.com/jQuery.ajax/