I am just wondering what general best practice is for saving data in Ajax Forms. In Spree ECommerce for example, every time you change a value in a list of objects (say you change the quantity of a certain Item in an Order), it updates the database with an Ajax call.
Is it better to have the User manually press "Save" or "Update" when they're done editing a form, or if you can (you have setup an ajax alternative), to just automatically save the data every time something changes?
It seems like Stack Overflow Careers saves a "Draft" of your profile every few seconds using some ajax thing.
As such, it seems like there's 3 ways to save data in a form if you have Ajax going:
User presses button, saves all data at once, not good if data is important
Save every time interval
Save every change
What do you recommend?
Good question. I don't think there's a one-size-fits-all best-practice that covers all situations. Generally, the more user-friendly your solution is, the greater the complexity of implementation, the less likely the potential for a proper gracefully degrading solution (unless you have been very, very careful).
Also, there are implications to whichever approach you have opted to go with. For example, autosaving periodically might not be a good idea where substantial data validation is involved. A user might type some stuff in, and get an error message after a few seconds. Instant feedback would be much more beneficial to the user in such a situation, as it is possible that the input which led to the failed validation was, say, a few actions ago, so it might be somewhat confusing to the user.
Saving whenever the user changes something (a keypress, a checkbox selection, etc.) would seem to be the way to go from a usability perspective, but again, it depends on what you are doing and could have negative side-effects. For example, if the user is on a slow connection, he/she might feel that your site is slow or buggy. It would also yield a lot more database queries than the old-school 'click save' method.
I guess an obvious way to get around some of the above caveats would be to incorporate on-the-spot client side validation, but what works in the end might well be down to what your hallway testers say.
Final recommendation: create the old-style 'click save to save' forms and enhance from there, making sure things don't break without javascript (unless you have express permission from a higher authority). Hope that wasn't all nonsense.
It all depends on the situation. If the form is going to change due to user input then you may be better served save/update form on every change. Otherwise wait for an explicit user action.
I can only see trouble on the horizon if you adopt an autosave strategy for a form..
I know this post is old, but I like this simple solution, if the user change som data on your form and try to leave page without saving it, I prompt a remember message
In a global .js:
var validate=false;
window.onbeforeunload = function() { if(validate) return "You made some changes, are you sure you want to leave?"; };
In the form page, (i did it in jquery):
$('input,textarea,select').change(function(){ validate=true; });
$('form').submit(function() { validate=false; });
BR!
Related
I need a Javascript function that serves the purpose shown below. I simply want to wait on the response from the server.
console.log('Before getting the city name.');
zip_code = '60601';
city_name = function_that_slowly_gets_city_name_from_server(zip_code);
console.log(city_name);
console.log('After getting the city name.');
Output in console:
Before getting the city name.
Chicago
After getting the city name.
I do not want the answer ('Chicago') sent to the console in a callback function. I understand that async:false is now taboo with $.ajax(), but I still need for it to work as shown above. I cannot find posts that provide a consistent, straightforward answer.
FOLLOW UP:
I've found many answers on StackOverflow that say synchronous calls are evil. Yet, is there a way to do it anyway?
Based on your comment, your use-case is a quick method of disabling user-interaction while the AJAX call is occurring to ensure the user can't do anything bad (e.g. start a duplicate request/race condition or navigate to a different part of the app, etc.). So maybe locking the thread ain't such a bad idea then, especially for an internal app that doesn't need a ton of frills?
But Here's the Problem:
The user can continue to queue events even during a locked thread. That means that any actions the user takes while a synchronous request is occurring (such as submitting a form) will continue to line up in the background, and will then begin firing as soon as the initial request is finished. So the threat of your user double or triple clicking out of impatience (or even just accidentally) -- and as a result causing duplicate calls to the database -- is very real and likely (for reference, I can double click in ~120ms pretty easily).
The same thread is also responsible for things that might surprise you, such as certain browser-level hotkeys or even exiting the tab at all, meaning yes, you could actually significantly delay the user from closing the application, though that's not likely for a low-traffic database. However, it's certainly not impossible, and it's definitely not desirable, even for an application that doesn't need all the frills of a commercial product.
So What Should I Do as a Quick Solution Instead?:
Well if you still need a quick solution that can effectively freeze the entirety of your application in one go, then depending on your existing code, this shouldn't be too bad either.
Make the request async, as is the default and standard. But before that request fires, select all elements typically in charge of event handling, disable them with the "disabled" attribute, and then re-enable them in the callback. Something like this:
var userStuff = $("input, button, submit, form");
userStuff.prop("disabled", true);
$.ajax({
// other ajax request settings ...
// ...
// ...
complete: (data) => {
userStuff.prop("disabled", false);
}
});
The elements contained within userStuff are just common elements that typically have some event-handling to them. It's up to you to determine if those elements are sufficient for your application, or if your application is so large that such a query could itself have a performance impact. But assuming that checks out, this will prevent the user from interacting with/queueing anything until the request has finished.
I Don't Care. Give me the Sync:
Well in that case, why not just use async: false as mentioned in your OP? I'm somewhat speculating here, but I believe it's not just async: false that's deprecated, but all means of synchronous XMLHttpRequest (which I believe $.ajax still uses under the hood), and I don't think there's any other synchronous alternative to that. So anything you do with synchronous network in mind is going to be evil, but at least in Chrome 89.0, $.ajax({async: false}) still works for me.
I have a very large webform that is the center of my Yii web application. The form actually consists of multiple html form elements, many of which are loaded via AJAX as needed.
Because of the form's size and complexity, having multiple save or submit buttons isn't really feasible. I would rather update each field in the database as it is edited by asynchrously AJAXing the new value to the server using jeditable or jeditable-like functionality.
Has anyone done anything like this? In theory I'm thinking I could set up an AJAX endpoint and have each control pass in its name, its new value, and the CRUD operation you want to perform. Then the endpoint can route the request appropriately based on some kind of map and return the product. It just seems like someone has to have solved this problem before and I don't want to waste hours reinventing the wheel.
Your thoughts on architecture/implementation are appreciated, thanks for your time.
In similar situation I decided to use CActiveForm only for easy validation by Yii standarts (it can use Ajax validation), avoiding "required" attribute. And of course to keep logical structure of the form in a good view.
In common you're right. I manually used jQuery to generate AJAX-request (and any other actions) to the controller and process them there as you want.
So you may use CRUD in controller (analyzing parameters in requests) and in your custom jQuery (using group selectors), but you can hardly do it in CActiveForm directly (and it's good: compacting mustn't always beat the logic and structure of models).
Any composite solution with javascript in PHP will affect on flexibility of your non-trivial application.
After sleeping on it last night, I found this post:
jQuery focus/blur on form, not individual inputs
I'm using a modified version of this at the client to update each form via AJAX, instead of updating each field. Each form automatically submits its data after a two seconds of inactivity. The downside is the client might lose some data if their browser crashes, but the benefit is I can mostly use Yii's built-in controller actions and I don't have to write a lot of custom PHP. Since my forms are small, but there are many of them, it seems to be working well so far.
Thanks Alexander for your excellent input and thanks Afnan for your help :)
In my application, users have a list of items that they can put in any order they like. The database schema looks like this:
Items
+ Id : int
+ Name : string
+ Order : int
so when the user puts things in order, it sets the Order field accordingly, so that I can sort it later. Great.
Now, I want to make the sort ajax-y, such that the user can drag and drop items into order (and use up/down arrows), and it will just automagically save everything. (If you're familiar with Netflix, they do a similar thing.)
The issue I'm having is that in order to persist the user's changes as they make them, I will need to do an AJAX call every time they do something. If the user moves an item from position 10 to position 1, that implies that I have to update 10 records in that little ajax call. Meanwhile, the user may have queued up 3 more AJAX calls to update other records.
This seems inefficient and like it might be error prone (due to race conditions and so on, if the AJAX calls take a long time.) Should I be worrying about this? Is there a more efficient way to do this? If it makes a difference, I expect most users will have fewer than 5 items to sort.
Since Javascript can't synchronize code, I agree that it would be difficult to implement code that would be sure to avoid race conditions, although I did find this article on implementing a Mutex in Javascript.
However, personally I think that rather than choose an option that is likely to result in race conditions, I would go with one of the following options:
Create a save button above the items, that when clicked will save the order to the database.
Create a timer that will save the order every five seconds (or whatever), if something has changed. You would still want a save button for this, so the users could force a save.
I would lean towards the latter. Obviously in both cases you would want some visual cue to the users that they have unsaved changes (like changing the background color of the items, for instance). You would most likely want to implement something that makes sure the user wants to leave the page with unsaved changes if you go with either of those options (like in Gmail, when you have unsaved changes in an email that you are composing).
Background
I'm working on a web application utilizing AJAX to fetch content/data and what have you - nothing out of the ordinary.
On the server-side certain events can happen that the client-side JavaScript framework needs to be notified about and vice versa. These events are not always related to the users immediate actions. It is not an option to wait for the next page refresh to include them in the document or to stick them in some hidden fields because the user might never submit a form.
Right now it is design in such a way that events to and from the server are riding a long with the users requests. For instance if the user clicks a 'view details' link this would fire a request to the server to fetch some HTML or JSON with details about the clicked item. Along with this request or rather the response, a server-side (invoked) event will return with the content.
Question/issue 1:
I'm unsure how to control the queue of events going to the server. They can ride along with user invoked events, but what if these does not occur, the events will get lost. I imagine having a timer setup up to send these events to the server in the case the user does not perform some action. What do you think?
Question/issue 2:
With regards to the responds, some being requested as HTML some as JSON it is a bit tricky as I would have to somehow wrap al this data for allow for both formalized (and unrelated) events and perhaps HTML content, depending on the request, to return to the client. Any suggestions? anything I should be away about, for instance returning HTML content wrapped in a JSON bundle?
Update:
Do you know of any framework that uses an approach like this, that I can look at for inspiration (that is a framework that wraps events/requests in a package along with data)?
I am tackling a similar problem to yours at the moment. On your first question, I was thinking of implementing some sort of timer on the client side that makes an asycnhronous call for the content on expiry.
On your second question, I normaly just return JSON representing the data I need, and then present it by manipulating the Document model. I prefer to keep things consistent.
As for best practices, I cant say for sure that what I am doing is or complies to any best practice, but it works for our present requirement.
You might want to also consider the performance impact of having multiple clients making asynchrounous calls to your web server at regular intervals.
How we can implement Two recaptcha user control on the same page.
Problem :
we have two views one for tell a friend about the site by sending e-mail and another authoring any note. the tell a friend part is hidden which send e-mail through ajax and note author part is visible so it is making problem when we need both but in different way.
Refactor to avoid usability issue
This doesn't seem reasonable and I would suggest to avoid this at all costs, because you have a serious usability issue if you do need two of them. Why would you need two captchas anyway? The main idea behind a captcha is that it assures that there was a person entering data in the form and not a computer.
So if there's one captcha on the page, you're assured. So if the first one was filled by a person, all other data is as well and you don't need a second one.
But I can see one scenario where two captchas could come into place. And that's when you'd have two <form> elements on the page. So a user can either submit one or the other. In this case user will always submit data from just one form and not both. So you could avoid this as well by either:
separating these two forms into two pages/views with an additional pre-condition page where a user would select one of the two forms
hiding captcha at first, but when a user starts entering data into one of the forms you could move the hidden DIV with captcha inside the form and display it. This way there would only be one captcha on the page and it would be on the form that the user is about to send
The second one is the one you'd want to avoid. If you give us more details what your business problem is, we could give you a much better answer.
Alternatives
Since you described your actual business problem I suggest you take a look at the honey pot trick, that is more frequently used for this kind of scenarios. Because if you used too many captchas on your site, people would get annoyed. They are tedious work, that's for sure. Honey pot trick may help you avoid these unnecessary data entering.
The other question is of course: Are your users logged in when they have these actions available? Especially the editing one. If they are, you can better mitigate this problem. You could set a time limit per user for sending out messages. Like few per minute. That's what a person would do. And of course store the information about sending out these emails, so you can still keep historical track of what users did so you can disable accounts of this gets abused. But when users are logged in they normally don't have to enter captchas since they've already identified themselves during authentication phase.
The ultimate question is of course: Why would a bot send out emails to friends? they wouldn't be able to send any kind of spam would they? What's the point then? It's more likely that bots will abuse your system if they can spam users anyhow. Either by sending email with content or leaving spam comments on your site. These forms need to be bot checked.