Rails AJAX Feedback, especially on error - javascript

I'd like to improve the AJAX feedback in my application (after I POST a remote form in my modals, etc.).
I already have some nice feedback showing a loading animation
$(document).ajaxStart(function(){
$('.loading-feedback').show()
})
$(document).ajaxStop(function(){
$('.loading-feedback').hide()
})
But I realize it's not enough : when my AJAX requests trigger a Completed 500 Internal Server Error in 1985ms... well nothing really happens for the user.
I would like, for example, to show an alert message on my frontend.
I already have some code that can display some flash messages I store in AJAX responses, which I'd like to reuse for this (for example, by showing oops, your AJAX request triggered a #{err_code} #{err_description}. Please tell the devs :D
I have the following code which successfully shows bootstrap flashes after AJAX requests (the content/type of the flashes being defined in my controllers)
application_controller.rb
after_filter :ajax_flash
def ajax_flash
return unless request.xhr?
if type = priority_flash
response.headers['X-Message'] = flash[type]
response.headers['X-Message-Type'] = type.to_s
flash.discard # don't want the flash to appear when you reload page
end
end
Related javascript
$(document).ajaxComplete(function(e, request, opts) {
fireFlash(request.getResponseHeader('X-Message'), request.getResponseHeader('X-Message-Type'));
# Where fireFlash is a function that displays a bootstrap alert
});
But now, If there is an error, my controller action will just return.
Is it possible to detect this, and for example to fill a flash
flash[:fatal] = "oops, your AJAX request triggered a #{err_code} #{err_description}. Please tell the devs :D"
That would the be displayed on my frontend ? (note that I don't know where to find err_code and err_description)

You don't need to use Ajax to create flash messages.
Since flash messages are non-persistent and removed from the session when they are rendered you can just create new flash messages by modifying the document.
This is a minimal flash implementation:
$(document).on('flash', function(e, key, message){
var $flash = $('<li class="alert flash js-created"></li>')
.addClass("alert-" + key)
.html(message);
$(this).find('.flashes').append($flash);
});
Turbolinks will clean out the flashes for use since it replaces the entire <body>.
You can add a global ajax failure handler by using ajaxError instead of ajaxStop.
var $doc = $(document);
$doc.ajaxError(function(event, jqxhr, settings, thrownError){
$doc.trigger('flash', ['error', jqxhr.status + thrownError]);
});

Use it this way.
$loader.fadeIn();
jqXHR = $.ajax({
url: "",
type: "POST",
data: {},
dataType: "json"
});
jqXHR.done(function( response ) {
});
jqXHR.fail(function( jqXHR, textStatus ) {
console.log( "Request failed: " + textStatus );
});
jqXHR.always(function( jqXHR, textStatus ) {
$loader.fadeOut();
});

Related

Show response from server on web page using AJAX?

I am developing a web app using HTML, PHP and JavaScript. I found a way to call PHP methods that run database operations from the client-side (HTML and JS) using AJAX, here's an example:
if (confirm('Sure you want to do that?')) {
$.ajax({
url: "myScripts.php",
type: "POST",
data: {
paramForOperation: myParam,
option: "doAction1"
},
cache: false,
success: function(response) {
//Here I reload or load another page after server is done
window.open("myPage.php", "_self");
}
});
}
So here I call the php file with the script that does an INSERT/ DELETE / WHATEVER on the database. It works fine, but what if I couldn't insert because the index already exists or any other reason? What if some type of data is wrong and I can't insert it? I know I can validate that on the server side using PHP, but how do I return a message saying "Operation complete" or "You should use numbers on X field"?
I thought of something like alert(response); but what will it return? An echo($msg); from my PHP functions? Is there a way to send the result message on that response thing in AJAX?
Thank you for your help.
Any output of the PHP script will be received in response. Remember, the PHP script runs on the server and just generates output. The PHP code itself never reaches the client.
So, you can just echo a message, and alert it in Response.
Bringing it up a notch, you can return a small piece of JSON or XML that can be parsed and which can contain an error message and some error code, so you script can also respond to that, and maybe change its behaviour (if the insert succeeded, add the new data to the page, for instance).
And of course, instead of returning always code 200 (meaning OKAY) from PHP, you could consider returning other HTTP status codes, so the code already indicates whether something went wrong or not. Depending on the status code, jQuery will execute either the success or the error handler, so it's easy to make different handlers for different situation.
Let your server respond with appropriate HTTP Status Codes and meaningful error messages. Use the error function of the ajax call.
$.ajax({
url: "myScripts.php",
type: "POST",
data: {},
success: function(response) {
/* no error occured, do stuff... */
}
error: function(jqXHR, textStatus, errorThrown) {
/* handle the error, add custom error messages to any DOM objects, ... */
console.log(textStatus, errorThrown);
}
Some docs: $.ajax and HTTP Status Codes

External server query not working

I am building a jQuery Mobile and PhoneGap application.
Here is some of my code to query data from an external server:
function showDetail(stationID){
$('#itemDetail').load('http://www.mywebsite.com/detailPage.php?stationId='+stationID, function(){
});
It works perfectly on my local machine, WAMP server, however when I compile the script and run on an actual device, Android, it does not work. The same thing applies to this form:
$('#addStationForm').on('submit', function(e) {
$.post( 'http://www.mywebsite.com/add_parser.php', $(this).serialize(), function(response) {
alert( response );
});
// disable default action
e.preventDefault();
});
Also I have whitelisted my server, so that is not the problem.
Any help would be greatly appriciated, thanks.
Are you trying to get data from a server and load it into a dom element?
If so use the .ajax function to perform a http request to get the data from the sever.
Check the following doc with good examples
http://api.jquery.com/jQuery.ajax/
Also provide more info about the type of data you are going to request receive to help you further in the configuration of the ajax call parameters.
You can also use getJSON but depending on your data and needs.
EDIT
Post is a shorthand of the ajax function.
Make sure your PHP does have the correct content-type in the headers. That is very important
Like:
header("Content-Type:text/plain");
or
header("Content-Type:text/html");
depending what you need, want.
Also you can debug the HTTP response using firebug or any other tool out there, and let us know what you got.
Also try to use the verbose option of the function, give it a try. Make sure you specify correctly the dataType and the data parameters.
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "html" // DATA TYPE is ALSO VERY IMPORTANT
})
.done(function() {
alert( "success" );
})
.fail(function( XMLHttpRequest, textStatus, errorThrown ) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
});
Also, when you said "when I compile the script and run on an actual device, Android, it does not work.", what errors you got? use the FAIL function of the http request to print the errors (like in the example above).

How to show error message when my server is down / not available while making JQuery request?

I have a code something goes like this;
<a4j:commandLink
actionListener="#{controller.validate}"
onclick="showFadeLoadingImg();"
oncomplete="confirmOperation();}"
value="#{actionItem.actionDisplayName}"
reRender="text1,text2">
</a4j:commandLink>
Here, when my server is down, my oncomplete event has jscript function confirmOperation(), which gets executed and undesired output from that function is being displayed. But, what I ultimately want is, when I click the button, I want to check whether I can able to connect to the server, and if not I have to show some error message like 'Unable to reach server' . Can you give me code example of achieving this?
Create an Ajax request like-
var jqAjax = $.ajax({
url: 'server URL',
type: "GET/POST",
dataType: "TYPE" ,
});
then, implement
jqAjax.fail(function(jqXHR, textStatus, errorThrown){
//Check the textStatus
});
Check the textStatus, for values - 0, 404, 500, timeout, abort, parsererror

Error Handling while File Updoading via an IFrame

The steps of my application are:
a client chooses several files via checkboxes,
a request is formed with the files' identifiers,
a client downloads the archive via an iframe: (a server finds these files, zips them, and then response is formed containing the zip archive 's bytes)
Here is the code of the iframe:
function makeSaveFrame(urlToServer) {
var ifrm = document.createElement("IFRAME");
ifrm.setAttribute("style", "display:none;");
ifrm.setAttribute("src", 'urlToServer';
ifrm.style.width = "0px";
ifrm.style.height = "0px";
document.body.appendChild(ifrm);
}
The response's type and header:
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachments; filename=\"" + fileName + ".zip\"");
The problem is: if something goes wrong, I need to send a reason to a client. As far as I am concerned, an error message must be of JSONObject type.
[if an error occurs on the server I can change the content type of the response and send a JSONObject, but I don't know how to filter the response and even how to catch an event of receiving a response in the iframe]
Please, share an expirience on this issue.
UPDATE
if I send
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "testMessage");
the bad response response arrives, but try/catch block around the makeSaveFrame() method doesn't catch this.
UPDATRE
I've tried this
var uploadForm = document.createElement('form');
uploadForm.name = 'uploadForm';
uploadForm.setAttribute("style", "display:none;");
document.body.appendChild(uploadForm);
Ext.Ajax.request({
url: 'requestURL',
form: uploadForm.getForm().getEl(),
isUpload : true,
method: 'post',
failure : function() {
Ext.MessageBox.show({
title : 'title',
msg : 'message',
buttons : Ext.MessageBox.OK
});
}
});
but the isUpload parameter kills a failure callback. So that, when a server answers with the bad response response, no error handler (failure callback) presents.
Since you have updated you question and not using frame anymore to request the content, you can use jquery, it can be similar to your updated content in question (ExtJS4 part in the end) ,
$.ajax({
url: 'requestURL',
form: uploadForm.serialize(),
method: 'post',
error : function(jqXHR, textStatus, errorThrown) {
// you can check the jqXHR object properties & methods to check
// the response status and contentType
alert("An error occured.");
}
});
Hope this helps.For more options on Jquery AJAX request follow JQuery reference
P.S : you need to add additional jquery library files to your page.
Please see this arcticle.
It seems that one can manipulate a content after upload, so that it is possible to apply a handler on it. Unfortunately, I had 2 problems in it:
in IE, 2 windows open and the second one (iframe) doesn't close after downloading a file (in FF works perfectly)
When a response arrives, the content is always empty, and I can't estimate it.
The next idea is to get cookies from the response header (iframe). This solution seems rather promising...

How to find the ajax status with jQuery 1.2.6

I'm using jQuery 1.2.6 (I know it's old, but I don't have a choice) I need to check the status of my ajax calls. I either want to use:
statusCode, or I could even use error(jqXHR, textStatus, errorThrown), except that textStatus, errorThrown and statusCode, aren't in my jQuery version.
Basically what I have to do, is know if the ajax call was aborted, or had an error for another reason. Any ideas how I can do this?
you could get the status text from the error callback:
$.ajax({
url: "/foo",
dataType: "text",
error: function(obj){
alert(obj.status + "\n" + obj.statusText);
}
});
http://jsfiddle.net/jnXQ4/
you can also get it from the complete callback if the request resulted in an error.
Edit: the ajax request also returns the XMLHttpRequest which you can then bind events to, though I'm not sure how cross-browser it is.
var request = $.ajax(options);
request.onabort = function(){
alert('aborted');
}

Categories