I have this simple form:
<form action="www.faildomain.com">
<input name="foo" value="bar">
<button type="submit">Submit</button>
</form>
In my case, the action will fail. But could it be that this is a valid action, but the user has experienced a connection error?
Are there different Javascript events generated or os this out of my control?
This is out of your control if you don't handle the submit event.
Basically, when you click on the submit button, your browser will do an HTTP POST request to your "action" URL.
If you want to check your inputs validity before sending it, what you'll have to do is to handle the form submission event: submit.
const myForm = document.getElementById('my-form');
// Add a listener to the submit event
myForm.addEventListener('submit', function (e) {
const errors = [];
// Check inputs...
if(errors.length) {
e.preventDefault(); // The browser will not make the HTTP POST request
return;
}
});
But, even with this code, you'll never know if the user has a network problem.
The only way you can check that kind of errors is by doing an asynchronous call to your backend route using Ajax (it's just an HTTP POST request, called asynchronously). For example, using jQuery:
$("#myForm").on("submit", function(e) {
event.preventDefault();
const data = {};
// Get data from form...
// Stop form from submitting normally
$.post("www.faildomain.com", data)
.done(function(data) {
// No problem
},
.fail(function (jqXHR, textStatus) {
// An error occured (the server responded with an error status, network issue, ...)
// More information about the error can be found in jqXHR and textStatus
},
.always(function () {
// This method is always executed whether there were an error or not
});
If you Submit it using Ajax you can get it via response headers. Take a look at this plugin:
http://malsup.com/jquery/form/#ajaxForm
it will help you a lot because it already have a method error for that.
Related
I am writing a basic function on my webpage, to POST data to another page on my webserver, however whenever I submit using this function, the server reports having received a GET request with no form data.
Unfortunately, I am completely at a loss when it comes to sorting this out, as I have no clue what is causing it.
function submit_function(event){
event.preventDefault();
var req = new XMLHttpRequest();
var fd = new FormData();
fd.append("username", "username");
fd.append("password", "password");
req.open("POST", "/auth/login", true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
req.send(fd);
return false;
}
Any help or insight at all is appreciated, it is getting late and there is a good chance I'm missing something obvious.
Issue was caused by a form submission interfering with the request, because it was nested as such.
document.getElementById("formid").onsubmit = function(e){ submit(e); }
The usual reason for this is that your code is triggered by a form submission, and you're not cancelling the form submission, so the browser sends the form (as a GET, apparently there's no type="POST" on the form element) and that prevents the ajax call from actually being made (even if your code runs to start it, tearing down the page to replace it with the result of the form submission prevents it from getting very far). Just ensure you're preventing the form submission (event.preventDefault()).
I am submitting a form using iron-form. However, when the server responds, I want to see what the response is so that I can:
Either close the form (if everything was OK)
Or highlight the "broken" fields (if the response was an error)
I realise I can easily listen to iron-form-error to see if there were any problems. The error comes back as Json, where I have key/value where the key is the field name, and the value is the error message.
In case the response was indeed an error, do I have to go through the response manually? Or is there a shorthand version to display the error messages automagically?
Thank you!
Are you doing any pre-validation with validators attached to the inputs? These will provide error messages that you have put in the error-message attribute of the input. When the response comes back you can just set the paper-input to invalid.
I have a password change dialog that is like this. It uses a validator to check that password 1 and password 2 are the same, but the server also checks this too. In this case it sends a valid json response (ie not an error) with the response json object containing an field that tells me that particular field is wrong (as a boolean). Here is a fragment of my response after earlier I have done var response = e.detail.response;
if (response.status) {
this.$.profiledialog.close();
this._setNopass(false); //just get this back to its default state
} else {
if (!response.passwd1) {
if (response.passwd2) {
this.$.pw1.invalid = true;
this.$.pw1.focus();
} else {
throw new Error('Profile Update Server Failure');
}
}
if (!response.passwd2) {
this.$.pw2.invalid = true;
this.$.pw2.focus();
}
}
I load a page from example.com on port 80, then from the loaded page, submit a form to the same server on a different port (as defined in the form action attribute).
(html)
<form id="enabledForm" action="http://example.com:39991/updateEnabled" method="POST">
(javascript)
$('#enabledForm').submit()
This works fine and the data is delivered as expected to the form action url, but the browser is redirected to the address of the POST request instead of staying on the requesting page.
If I use
$('#enabledForm').submit(function (event) {
event.preventDefault();
});
or
$('#enabledForm').submit(function (event) {
return false;
});
then the server receives no data but the page is not redirected.
if I add an alert within the event handler then the alert is not shown.
$('#enabledForm').submit(function (event) {
alert('inside submit event handler');
return false;
});
Clearly I'm soing something wrong but after hours of headbanging and trying everything I can think of I'm stuck.
What to do?
You have two basic options here:
Have the server return a 204 No Content response and forget about using JS entirely
Prevent the submission of the form with JS and send the data to the URL with Ajax instead
No content:
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent.
How you set the HTTP response status code depends on your server side language / framework. For example:
In Catalyst it would be something like:
$c->response->status(204);
In PHP it would be:
http_response_code(204);
There are many Ajax tutorials out there, so I'm not going to provide another one. The jQuery documentation has a detailed section on Ajax.
Note that since you are working across origins (different ports), you will need to circumvent the Same Origin Policy. The standard way to do that is with CORS.
Sending a form would automatically change your browser URL (and refresh view).You should use an Ajax request to send informations to your server and eventually retrieve completion (success, error, informations...).
Extract your inputs' values to an object via Jquery and send your request via Jquery.post or Jquery.get
$('#enabledForm').submit(function (event) {
//Prevent natual post
event.preventDefault();
//Retrieve inputs values
var data = {}
$('#enabledForm input,textarea').each(function(index){
data[$(this).attr('name')] = $(this).val();
});
//Send request
$.post('http://example.com:3999/updateEnabled',data,function(response){
//Parse response if you want to inform user about success of operation
});
});
I don't know if val() is usable with all of yout inputs, but it's easy to adapt...
I'm trying to attach a callback to the "Send mail" ajax action in Gmail. I've been able to differentiate a Send mail action from other AJAX actions based on the request payload but have been unable to hook into the actual AJAX call.
Thus far, I've tried using overriding the XMLHttpRequest.open() method as detailed here. That hasn't worked. I've also tried overriding XMLHttpRequest.send(). Also failed.
Any thoughts? Much thanks in advance.
Google's trick is that they send the request from inside an iframe which has it's own JavaScript environment. However, since it is loaded from the same origin as the parent, you can still easily manipulate it even from the browser console:
[].slice.apply(document.querySelectorAll('iframe')).forEach(function (iframe) {
try {
var xhrProto = iframe.contentWindow.XMLHttpRequest.prototype;
var origOpen = xhrProto.open;
xhrProto.open = function () {
console.log('DO SOMETHING', arguments);
return origOpen.apply(this, arguments);
};
} catch (e) {}
});
You might want to use a MutationObserver to detect newly added iframes reliably.
I'm working on a project which uses user authentication. I'm facing a issue with my AJAX requests if there is no authenticated session present when the request is made.
I've a session timeout of 3min, so if the user keeps idle for 3 min then do some action which causes a AJAX request then the request will fail and return a 403 error. Here What I'm planning to do is intercept all the AJAX request from the page and sent a ping to the server which will return a JSON object saying whether there is a valid session. If there is one then the client will continue with the current request else it will reload the current page which will take the user to the login page and the user has to provide the credentials again.
Here is my implementation.
$("#param-ajax").ajaxSend(function(evt, request, settings) {
var pingurl = GtsJQuery.getContextPath() + '/ping.json';
var escapedurl = pingurl.replace(/\//g, "\\/");
var regexpr1 = eval('/^' + escapedurl + '\\?.*$/');
var regexpr2 = eval('/^' + escapedurl + '$/');
// Proceed with the ping only if the url is not the ping url else it will
// cause recursive calls which will never end.
if (!regexpr1.test(settings.url) && !regexpr2.test(settings.url)) {
var timeout = false;
$.ajax({
url : pingurl,
cache : false,
data : {
url : settings.url
},
async : false,
complete : function(request, status) {
if (status == "error") {
try {
// GtsJQuery.getJsonObject() converts the string
// response to a JSON object
var result = GtsJQuery
.getJsonObject(request.responseText)
if (result.timeout) {
timeout = true;
return;
}
} catch (e) {
// ignore the error. This should never occure.
}
}
}
});
// Reload the window if there is a timeout -- means there is no valid
// sesstion
if (timeout) {
window.location.reload();
}
}
});
Here everything work fine included the window.location.reload(), but the original ajax request is not aborted. Since the original AJAX request is not aborted after the page reload is triggered, the AJAX request also is sent to the server. I want some mechanism which will allow me to abort the original request if the timeout turns out to be true.
This post offers some answer, but the issue remains with the third party plugins like datatables which uses AJAX. We cannot write a error handler for those AJAX requests.
Thank you.
If I am understanding the situation, you do not need any of that. In your original ajax request, simply add an error function that will redirect the user.
errHandler = function(XMLHttpRequest, textStatus, errorThrown) {
if( textStatus.match(/forbidden/i) ) {
redirectUserToLoginHere();
}
}
$.ajax({
success: yourFunctionHere,
error: errHandler
})
Then you might be able to make some ajax wrapper which always has that errHandler so you don't have to place it in every single ajax call.
EDIT:
after some experimentation, if an 'ajaxSend' handler throws an Error, then the original request will never be sent.
Also, if the handler does
document.location = '/login';
then the original request is never sent.
Hopefully that helps :)
I changed my concept now, I'm checking for the xmlHTTPRequest in the server side using the request header 'x-requested-with'.
If it is a xmlHTTPRequest then 'x-requested-with' will have the value 'XMLHttpRequest'. Both the javascript libraries(EXTjs and jQuery) I'm using sets this header correctly.
Here is my server side code
boolean isAjaxRequest = StringUtils.endsWithIgnoreCase(request.getHeader("x-requested-with"), "XMLHttpRequest")
EDIT
If the given request is a ajax request the response will be json data which will have status 403 and it will contain a key called timeout with value true
ex: {timeout: true, ....}
Then we will handle this in the $.ajaxError() event handler will handle the error. If the error status is 403 and the timeout value is true then I'll reload the page.