I have a form that the user submits and returns a result, but it takes a couple of seconds to return the result. I know I can use grails formRemote http://grails.org/doc/latest/ref/Tags/formRemote.html to execute the call asynchronously and update a div on the page, but what I want to do is show another page entirely (with some wait graphics and other information).
Is there an easy way to do this in grails?
You can send data to server asynchroniously (ajax, formRemote), showing 'wait graphics' util you get a response. And redirect to result page right after getting response (and you should have to store state somewhere, and probably have unique url for result page)
Related
This question already has answers here:
Prevent user from seeing previously visited secured page after logout
(7 answers)
Closed 6 years ago.
I have a JSP page with a form where you fill up certain details. On submitting the form i call a servlet which then updates details in a database after that i redirect to a page i display a confirmation message to the user.
The problem i have here is when the user clicks back he goes to the form page again where if he clicks a submit button, it creates a new record in the database.
Consider this similar to a shopping cart example where in this case he would buy the same item twice. But the only problem here is i cannot handle this in backend, i.e. the database can never know a redundant operation is taking place.
I need to handle this from the client side.Bit weird but i have to do it this way.
Basically when the user clicks the back button i don't want him to be able to go to the form page and may be just to some other page.
This is a typical HTML form issue, you can solve it through any one of following methods
1) Server side (page expiration): Since you've mentioned that the page refreshes and goes to the confirmation. You can set no-cache and add a page expiration time as -1 to the page you have that form.
So that when user presses the back button, he will see that the page has expired. He will be forced to load the page freshly. This is the behavior that I see in most banking websites.
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
2) Using turn Key method: When the form loads, you can generate a random key in session memory and also embed it as a hidden value in the page.
During form submission, check the submitted hidden key against the value in session. If exists, then add the entry to database otherwise you can reload the page with a fresh key for the user (who might have done that unintentionally).
In load balanced or web farms, consider persisting the turn key in Database against the current user.
3) Client Side (Not recommended) : You can restrict the user from using the browser back button by removing the page from the history. (One side effect is that it will remove the entire history for that browser tab/window)
history.pushState(null, null, document.title);
window.addEventListener('popstate', function () {
history.pushState(null, null, document.title);
});
If you need the same support for older browsers where push and pop states are not supported, you can use following snippet.
<script>
function preventBack() {
window.history.forward();
}
setTimeout("preventBack()", 0);
window.onunload = function() {
null
};
</script>
Before redirecting to the JSP page send these headers with the response from the controller so that the page is not stored in cache and the browser will always request a new page from the server.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0);
So every time you go back to that page a new page will be requested from the server and will be displayed with the cleared input fields.
You could implement a PRG-Pattern (https://en.wikipedia.org/wiki/Post/Redirect/Get) using php.
Basically, after successfully submitting the form you redirect to a confirmation page which informs the user that their submission was successful/accepted/etc. and also set a variable which you can later use to check if said submission has been submitted yet.
When the user tries to reload said page or go back you can check the variable and display either the form again or the confirmation page based on if the submission has been submitted already.
I think following flow is the best:
Client submits data to server
Servlet processes it
It returns HTTP 303 redirect to client
Client redirects to success page
After this flow, refresh, back button will work properly.
For more information read Simple Post-Redirect-Get code example
I am using GWT 2.5.1.
In my GWT web app I have a ComplexPanel object which contains a set of fields(widgets). There are a suggested field (on panel) which gives me the opportunity to find object and info about it. Fields (10-15 of them) contain info about that object.
The problem is when user (client side) has a slow internet connection, fields on form are updated with a delay. And if in moment of delay user click 'Save' button (AsyncCallback), old data (which is not updated) posted to the server.
How it works:
1. Server receive callback from the form and start to processing the data.
2. Server refresh all the fields with new data and end the works.
3. Javascript updating the data on form using about 10 requests.
But: internet is slow and one part of data is refreshed and other no.
4. User click SAVE and mixed data goes to the server.
I need to know (from server side) when all the field are refreshed on client side and server can proceed with a next post request.
Thanks in any advice.
Perform a validation check on click of the save button. There are several things you can do as per your requirement. I have listed one way to validate it.
Set a flag before making the async call as false. For instance, isLoaded = false
Once you have all the fields just update it to true, i.e. isLoaded = true
On save button handler check for isLoaded flag. If false, prompt a message, else save.
Update:
You can count the number of response received. You know that you will get 10 response. So for every response received increment a counter. Activate save only if you have all 10 response recieved.
For a clean way to do this, use gwt-async-future.
I have two jsp page: page1.jsp with a form and page2.jsp which displays a message to tell the user if the record insert happened or not.
If the form is successfully submitted and the user refreshes the page2, another insert happens.
I wouldn't to use a session variable, and setting a request attribute in the page2 doesn't resolve the issue (it seems to not work).
You can give a try to this:
From page1.jsp set a request attribute, when control reaches to
page2.jsp check for that request attribute if it is there redirect the
control to same page2.jsp. In this way when control is redirected to
same or other resource, previous request and response objects are no
more there(i.e. both request and response object will destroy because
HTTP is stateless protocol) And like this after redirection there will
be no data related to previous request and on refreshing the page2.jsp it
will not repeat the previous task.
I am not sure but in one of my application I used the same for the purpose. Let me know if anyone has a better alternative.
I am working on existing code that uses CGI::FormBuilder, and I've gone through all of the documentation to see how this might work, and I'm not 100% convinced that it will. The code has several free-form fields and 3 buttons: Update, Cancel and Test. The test button sends an email using settings entered into the fields.
In the JS for the form, I use an ajax call when "Test" is clicked so that the perl code in the form executes. The update and cancel buttons return like the form is supposed to when it is submitted. The reason for this is that when the test email is sent, I don't want the user to be taken to a returned page, but remain on the form with the values intact, so that if the values are correct, the user does not have to re-enter them when they want to update the actual values (which updates the values in my DB). Apparently, since the form isn't being "submitted," the values that it attempts to use on this "test" are the values loaded into the form with the page opens - it isn't using the values the user input before hitting the test button. Is there a way to make this happen?
Long question short: with CGI::FormBuilder, can I get the values currently in the fields via PERL without submitting the page? Thanks!
Short answer: yes.
Medium answer: Yes. You can use javascript in the page to send information to your server side application.
Long answer:
You seem to have some confusion about how server and client side code interact with webpages. This is pretty common. Many people expect their to be some kind of communication between the rendered page and the program that generated it. AJAX and related technologies blur the lines here and make things more confusing.
Here's a timeline of a simple, old-school CGI form:
Client requests page. Server receives page request. Server dispatches
to CGI script.
Server executes CGI script.
Server sends result of CGI script to client.
Client renders script results.
User fills out form.
User clicks "Submit". Client requests page with parameter information (details vary with type of request, form configuration).'
Server receives page request.
Server dispatches to CGI script.
Server executes CGI script. Server sends result of CGI script to client.
Client renders script results.
Each message from the Client is handled separately.
AJAX lets you send messages to the server and get the response without clearing the currently loaded page.
So, just throw some javascript code into the html, and set up an onModify handler that will make an AJAX request and pass data back to the server. The AJAX request is just another HTTP request, just like those above, but it runs in the backgound. All you need to do is catch the submitted data and respond. Your javascript needs to catch the response and do something with it.
Answer to the short question is "No".
Answer to the long question is "Yes".
All you need to have two "Submit" buttons: "Submit" and "Test".
The submit by Test will send form to the CGI and CGI will only validate the fields' values and render same form with same values back and message if there is an error in fields.
I have an ASP page that takes two arguments on the querystring. On the page is a form that posts back to itself.
If I do the form post once, and then try to refresh the page, it doesn't repost the form. It loads the page as though it were loading for the first time, missing the querystring values.
Is there a way to ALWAYS force a repost when I refresh a page that is the result of a FORM post?
It sounds like the problem you're having is loss of some essential parameters to your page when posting. In ASP there are two primary methods of passing parameters, in the url string via GET or from a form POST. The former passes you values in the QueryString dictionary while the latter gives them to you in the Form dictionary. Fortunately for you it is possible to accept a parameter that exists in EITHER dictionary by looking to Request object:
Request["a"] will find a regardless of being in Request.QueryString["a"] or Request.Form["a"].
This will help you in your current dilemma because you can simply write your querystring parameters to your Form on initial load of the page as <input type="hidden" fields. On subsequent posts your Request["a"] search for your parameters will find them regardless of being passed in the URL (on initial load) or via post on subsequent calls.
The problem was that I was going into the Firefox address bar and pressing Enter. This caused the URL to reload (and of course it didn't have the querystring after it reposted). So -- lesson is to do a check of the incoming vars and form vars to see if the page has been manually refreshed I suppose...
You could still maintain the submitted values in this situation.
What you would need to do is log the most recent request in either a Cookie, Session or data/file store, and on each request, check to see if the request was handled before you remove the data.
Since what you were after was the querystring it could just be something like this:
Response.Cookies("tempdata")("querystring") = Request.ServerVariables("QUERY_STRING")
Response.Cookies("tempdata")("querystring_handled") = false
then when you are done with that request you can clear the cookie value or set the querystring_handled = true.
There are probably situations where this could cause some conflicts, but just so you know, it is still going to be possible for you to remember the request once it is received by the server.
Which action does the form use: GET or POST? Normally, a form would use the POST action, but in this case, if you refresh the page with the posted form, you will not get anything in query string, because query string only gets passed via the GET action. Assuming that this issue is not caused by page caching, it seems to me like it works as designed (if the form POSTs data). Just make sure that you process the form variables if the query string is missing.