should input buttons that submit ajax requests be disabled after a request is made untl the response is received.
Im thinking specifically adding products to a shopping basket using a button.
Im trying to make the process as bullit proof as possible but a quite new to using ajax so dont know the best practices on these situations.
Yes, I think that is a great practice. But, it would also help to give the user a "processing" (or some other phrase) notice while you've disabled the button.
Disabling input is a very useful UI element to prevent the user from doing something bad, but I would caution against relying on it too much.
You should probably also do some server side checking to make sure you aren't receiving a duplicate request. This will shield you from browser bugs/non js-browsers etc.
If you want to make it as bullet proof as possible, then you need to show an animation right before you kick off the AJAX request, and handle both success and failure of that request.
As far as preventing an additional request, that depends on your specific action. In your case, updating a cart, it could go both ways. If I "click to add item to cart" once, but there are other items on the page that I could also add to my cart, let me click on the other "Add to Cart" button...right?
Related
I have a server-side "cart" variable that gets updated via an AJAX call when a button is clicked (I'm using Shopify, if it matters, but I feel that this is a general question). I am using AJAX to reload a div once the cart changes. The problem I encountered was this:
I submit the "update cart" AJAX call
Immediately after I try to reload the div
Depending on the exact timing, maybe 1 out of every 10 times the reload would use the old cart data, since the cart change hadn't registered on the server yet.
I came up with a solution to use setInterval, but I think there are some serious problems with this method. I'll show the code first, then share my concerns.
function addToCart(prodid,prodHandle,sizeString){
var oldSpaces = getNumSpaces(); //gets the number of "free spaces" to display
//the actual call to update the cart
push_to_queue(prodid, 1, {}, Shopify.moveAlong);
//now wait for the number of items to change (ignore the possibility of cart update
//failure, that's handled elsewhere)
var timerVar = setInterval(function(){
var newSpaces = getNumSpaces();
if(newSpaces != oldSpaces)
{
$( document ).ready(function() {
$("#toybox").load(" #toybox > *");
clearInterval(timerVar);
});
}
},200);
};
My concerns are that this feels extremely hacky. I'm running my update function once every 200ms. Is there a way (in general preferably but in shopify only if need be) to ask the server itself to let me know when something has changed?
This seems like a strange question. The server does not change the cart. The client changes the cart. So when you ask for a preferable way to ask the server to let you know when something has changed, the answer will always be, that is never going to happen.
If you want to know when the cart changes, you will always know since you can listen to all cart events client side. Since you are coding up things client side, you need not trouble yourself with server events.
That is how Shopify cart works, and you are asking for advice with that in mind, so I hope this helps you. Polling every 200ms, or N ms or any seconds is a pointless exercise in wasting browser cycles.
What happens if a user leaves the page while its processing via Ajax? Will the processing continue? I use Ajax to display a loading image while it executes a script that could take a long time and am worried if users leave the page, the processing of this script will stop. I want it to contiue whether or not the user is on the page. Is this possible?
I guess if the query is sent to the processing asp/php file and ajax is only waiting for the response, the query is successful.
But I think, you must add a control, like and alert asking if you would like to stay on this page or leave.
What I mean is, try writing a comment or an answer on this page and try to press the back button, an alert will appear.
With this method, you make sure the user doesn't leave before the query is complete.
I am taking my first steps with Ajax while working on a Grails application. I am using
<g:form ...>
<g:submitToRemote ... />
</g:form>
in the most simple way and it worked great out of the box (Thanks grails!). The problem is, that the Ajax call needs about 2 seconds to return and update the html (at least on the test system) and during that time, the user can (and actually does quite often) hit the submit button again. At the moment this results in a 2nd call being made that finally ruins the output (an error msg says, that one cannot submit the same data twice).
What is the best way to prevent this?
Thanks in advance for your input!
The best way to handle this is to disable the submit button in your onSubmit() function. Honestly, I don't know why more sites don't do this. I often go the next step and instead of disabling the submit button, I put the submit button in a span tag and replace the contents of the span tag with static text "Please wait..." That way your users get visual feedback they pressed the button and "top men are working on it".
As dj_segfault said you can do that.
If you want to validate this in your controller, take a look in "Handling Duplicate Form Submissions" in the official docs:
http://grails.org/doc/latest/guide/theWebLayer.html#formtokens
In grails, I use the mechanism below in order to implement what I'd call a conditional server-side-triggered dialog: When a form is submitted, data must first be processed by a controller. Based on the outcome, there must either be a) a modal Yes/No confirmation in front of the "old" screen or b) a redirect to a new controller/view replacing the "old" screen (no confirmation required).
So here's my current approach:
In the originating view, I have a <g:formRemote name="requestForm" url="[controller:'test', action:'testRequest']", update:"dummyRegion"> and a
<span id="dummyRegion"> which is hidden by CSS
When submitting the form, the test controller checks if a confirmation is necessary and if so, renders a template with a yui-based dialog including Yes No buttons in front of the old screen (which works fine because the dialog "comes from" the dummyRegion, not overwriting the page). When Yes is pressed, the right other controller & action is called and the old screen is replaced, if No is pressed, the dialog is cancelled and the "old" screen is shown again without the dialog. Works well until here.
When submitting the form and test controller sees that NO confirmation is necessary, I would usually directly redirect to the right other controller & action. But the problem is that the corresponding view of that controller does not appear because it is rendered in the invisble dummyRegion as well. So I currently use a GSP template including a javascript redirect which I render instead. However a javascript redirect is often not allowed by the browser and I think it's not a clean solution.
So (finally ;-) my question is: How do I get a controller redirect to cause the corresponding view to "break out" of my AJAX dummyRegion, replacing the whole screen again?
Or: Do you have a better approach for what I have in mind? But please note that I cannot check on the client side whether the confirmation is necessary, there needs to be a server call! Also I'd like to avoid that the whole page has to be refreshed just for the confirmation dialog to pop up (which would also be possible without AJAX).
Thanks for any hints!
I know, it's not an "integrated" solution, but have you considered to do this "manually" with some JS library of your choice (my personal choice would be jQuery, but any other of the established libraries should do the trick)? This way you wouldn't depend on any update "region", but could do whatever you want (such as updating any DOM element) in the response handler of the AJAX request.
Just a thought. My personal experience is that the "built-in" AJAX/JS stuff in Grails often lacks some flexibility and I've always been better off just doing everything in plain jQuery.
This sounds like a good use-case for using web flows. If you want to show Form A, do some kind of check, and then either move onto NextScreen or show a Dialog that later redirects to NextScreen, then you could accomplish this with a flow:
def shoppingCartFlow = {
showFormA {
on("submit") {
if(needToShowDialog())return
}.to "showNextScreen"
on("return").to "showDialog"
}
showDialog {
on("submit").to "showNextScreen"
}
showNextScreen {
redirect(controller:"nextController", action:"nextAction")
}
}
Then you create a showDialog.gsp that pops up the dialog.
--EDIT--
But, you want an Ajax response to the first form submit, which WebFlow does not support. This tutorial, though, will teach you how to Ajaxify your web flow.
for example:
user submit a comment , I add the comment in the page by javascript , then do the ajax. if ajax post failed ,tell user that something wrong happend.
in this way , it can improve user experience . and the probability of ajax failed is not low. but I didn't seen which site is using this technology , so is this method possible?
Actually, I'd say that stackoverflow uses this technique :
Make sure you are using firebug, and have the console displayed on the bottom of your browser scree
Click on (for instance) the arrow to upvote
you will see the arrow immediatly becomes orange, to indicate you have upvoted)
but looking at firebug's console, you will see the Ajax request starts only after the arrow has changed color -- or, at least, it is not finised yet when the arrow has changed color.
Considering the probably of the Ajax request failing is pretty low, changing the arrow immediatly indicates the user his vote has been taken into account... Even if it's not true before a couple milliseconds ;-)
You can add the comment via Javascript but you've also pointed out exactly why you shouldn't: what if it fails? Do you then remove the content?
In my opinion, adding it to the page implies to the user that it has worked. I would leave the comment in a form field until the AJAX submit succeeds. If that fails you can tell the user and they can try to submit again or whatever.
Of course, there is no functional reason why you couldn't do this.
Yes there is nothing stopping you doing this.
You add the comment in an element you create in javascript post the data and get the response code back form the ajax post.