Wicket - confirmation on panel replace / remove to save unsaved data - java

i have a Wicket SPA web application where i want the user to confirm that on panel panel replace / remove he wants the data entered in the panel saved or not?
My app structur looks like this
<body>
<nav>
<a wicket:id="home">Home</a>
<a wicket:id="documents">Documents</a>
<a wicket:id="user">Users</a>
<a wicket:id="logout">Logout</a>
</nav>
<main wicket:id="panel"></main>
</body>
Now have a addDocumentPanel which is replaced into the wicket:id='panel' when the user clicks somewhere 'Add new Document'. In this panel the user has to fill several fields in a formular. Now when the user clicks on for example Home the addDocumentPanel is replaced by a homePanel. When this happens i want to ask the user if he wants to save unsaved data.
A good place to do it SOLID is the onRemove() function of the Panel but here i dont have any AjaxRequestTarget or other things to ask user either through JavaScript or wickets ModalWindow.
Any ideas how to do it?

Add a behavior to all of the navigation links that when clicked does a simple logic of checking if the form contains any dirty (unsaved) data. I guess this can be done on the client side without a server roundtrip and upon finding the form is dirty, you can show a window.alert dialog to the user.
A more heavy approach is to use your own AjaxLink subclass for the navigation links and in the onClick(AjaxRequestTarget target) handler do the ModalWindow magic. This however causes your links to contain non-bookmarkable urls. If it's not a concern (this is an internal application, not internet facing web site), then this may work as well.

Related

Prevent form resubmit after pressing back button

I am in bit of a delicate situation here. In my organization we design stock management systems and it is a web application based on JSP pages and servlets which handles them.
I have been asked to fix a specific problem. We have a JSP page with an HTML form table where there are stock details. When user enters the details manually and submit the form, stock details updated in the database and it works fine.
Problem is this : When the user press the browser's back button, user can come to the previous page where he submitted the details. And when the user submit this, data is saved once more to the database.I need to prevent this behaviour.(Something likeclear and reload the page.)
Things I did so far : clear the browser cache.Code works fine but not the expected result.
Unfortunately I cannot share the code due to company regulations. What I need is a help to prevent this behaviour or a workaround.
Thanks in advance..
You can use a javascript function with the help of a hidden attribute to reload the web page. When the user press the back button,based on the value of the hidden attribute, page will be reloaded without loading the cached page.
Your approach of clearing cache is correct. Coupled with that, you can use this approach.
<input type="hidden" id="refreshed" value="no">
<script type="text/javascript">
onload=function(){
var e=document.getElementById("refreshed");
if(e.value=="no")e.value="yes";
else{e.value="no";location.reload();}
}
</script>
One drawback of this approach is if your clients' browsers have disabled JS, this will not work.Otherwise it should work.
When the user press the browser's back button, user can come to the
previous page where he submitted the details. And when the user submit
this, data is saved once more to the database.
According to how you described it, that is based on a doGet request. Which means every time you visit that URL, it will send the request with whatever parameters were added.
As someone already mentioned, if you switch the form to a post method and switch the Servlet to a doPost, you won't have this issue anymore.
Alternatively you can circumvent this with a javascript solution. Here are some options:
You can check if the user clicked the back button, disable form if true.
Another way is by storing a cookie which you check on page load, if it exists you can disable the form.
You can use this code also
$(document).ready(function() {
function disableBack() { window.history.forward() }
window.onload = disableBack();
window.onpageshow = function(evt) { if (evt.persisted) disableBack() }
});
You must use a Post-Redirect-Get pattern: https://en.m.wikipedia.org/wiki/Post/Redirect/Get.
Actually, every use of standard HTML forms with method="post" should be implemented with that pattern. It doesn't have any use for AJAX-posted forms, which actually could be another solution but will require more work and probably some architectural changes.
I had this same problem while building a django web app, and my solution was to not allow caching of the html that contains the form. In your request handler, do not allow the browser to cache the page. This will force the browser to get the page fresh from the document.
Which, in this case, you can just verify in your request handler if the requested form has already been submitted.
My code for reference:
from django.views.decorators.cache import never_cache
#never_cache
def GetForm(request, pk):
# Logic #
if (IsFormCompleted(pk)):
# Handle request #
Here is a solution.
give a random id in a hidden field on the form. Then on the server side, if the user resubmit, check if the random id already on the database. If so, redirect user.

button click() does not provide any response

I'm having issues with logging into specific website via HtmlUnit methods.
The site form's submit button looks like this:
<td>
<input type="button" value="Login!" onclick="encPass(UTM_STUDIO_ADMIN);" class="normalButton">
</td>
Mine code snippet:
final HtmlButtonInput submitLogin = form.getInputByValue("Login!");
HtmlPage returnPage = submitLogin.click();
System.out.println(returnPage.asText());
Yet, it prints the logging site with username and password fields fulfilled, that's all.
WebClient config:
wclient.getOptions().setPrintContentOnFailingStatusCode(false);
wclient.getOptions().setCssEnabled(false);
wclient.getOptions().setThrowExceptionOnFailingStatusCode(false);
wclient.getOptions().setThrowExceptionOnScriptError(false);
wclient.getOptions().setUseInsecureSSL(true);
wclient.getOptions().setJavaScriptEnabled(false);
I've been already trying to log via my own added button, and played with ideas of waiting, enabling JS, redirecting etc., but I'm new in the topic so it does not guarantee I can uncheck any ideas as already tried.
Your button is of type button (not submit). In this case the browser renders only a button but the application developer is responsible for doing something if the user clicks the button. In you case the button will trigger some javascript.
But you have disabled Javscript by
wclient.getOptions().setJavaScriptEnabled(false);
Maybe your problem goes away if you enable javascript.
In general it is a good idea to start with the default setting when facing any problems. The defaults are set in a way to be as close as possible to the real browsers.

Extracting and processing textarea value form without changing the page

I have a JSP file in which there are two textareas and a submit button all in a form ;
<form action="" method="post">
<textarea name="inConsole" id="in" cols="100" rows="10"> </textarea> <br/>
<input type="submit" name="Send Command"/> <br/>
<textarea name="outConsole" id="out" cols="100" rows="10"></textarea>
</form>
this page is supposed to work like any SQL program. so the user types a command in the first textarea and clicks submit, then the value of textarea will be extracted to a field and a method will take care of the command and return a log (1 row inserted, error:bad syntax etc) which will be displayed in the second textarea.
I know how for example make a login page and send data and redirect user to a new page(new jsp) file if user pass is correct.
what I can't find is how can I do all the things that I said above without going to a new page while using form action.
I have checked other questions that linked the action attribute to a servlet which was confusing for me( the way that a servlet was called). I'm looking forward to use a simple scriptlet for this purpose like the one I used for my login page:
<%
DatabaseLoginTest dbLogTest = new DatabaseLoginTest();
if (dbLogTest.DBLoginChecker(request.getParameter("user"), request.getParameter("pass")) == true){
%>
<p>Login Successful</p>
<% } else { %>
<p>Login Failed</p>
<% } %>
also I'm aware that adding java scripts(not Javascript scripts:) ) to html isn't a good practice(and the reasons for it) but I think this might be easier for a simple program that I'm working on.
p.s: I'm using tomcat and Intellij for developing this web application
and I have made a custom SQL so I only need the code that gives me the textarea value and the one that sets the other one's value
Update: now I know I should use javascript but I don't know how can I send the data extracted by javascript to a java method.
If you want to do this while remaining in the same page, you have to use Javascript. This is because if you want the server to be able to re-render the page, there has to be a page refresh.
You would need to write onClick handler for the submit button and make a Ajax call to your server to a specific URL with the user input. This URL would serve the data needed for the necessary UI changes.
You can use a scriptlet to generate the HTML that would be shown in the webpage but this would only suffice for a simple use-case and it would be a lot simpler if, say, your service returned just the data required to make the UI change and actual UI change is handled by the JS.
Also,I don't think it is a bad practice to embed JS in HTML. Sure, you can optimize this by including a JS source file but that's a separate optimization.

Can we submit the specific html form using frameset and give the feeling of ajax in some sense?

i am working on legacy project. In one of the jsp, it has cascaded frames something like this
<frameset >
<frame src="Welcome.jsp">
<frameset cols="9,*" >
<frame src="Customer.jsp">
<frame src="Account.jsp">
</frameset>
</frameset>
I have skipped the jsp code between frameset/frames.
Now inside one account.jsp ,I am having the html form which gets submitted on click of submit button.The
experience i see on UI is that only account.jsp is refreshed with new data(leaving other jsps like welcome and customer intact). My understanding was this is
possible only through ajax request. But when i drilled down , i found it is same simple logic of form submission .
My question is then how come only that
particluar frame is refreshed but not the complete page. Is it frameset feature? I tried to do the googling about it but could not find relation of specific form
submission with frameset?
If you submit a form on an iframe, only that iframe will refresh. That's just how it works. I could not find documentation on it either. It behaves like an entirely separate tab to a degree. You can navigate in the frame as if it were a different tab, for example. If you want to refresh the parent page, use this:parent.location.href = parent.location.href
You can consider the frames to be different instances of browsers but presenting on same screen, (just like tabbed browsing) , we use frames only when we need all the parts to be detached and work as the way u said its working, if you want to update other frames from one frame use javascript to get hold of that frame and set the src property for that frame , if you want to revamp the whole page, then window.top.src = new_page

Why does Wicket change the action attribute of a non-Wicket form tag?

In the base template for the pages of my Wicket application, there's a form I don't want Wicket to handle, like this:
<form id="myForm" action="">
<!-- input fields and submit button -->
</form>
I left the action attribute empty to always send it to the current page. On the application's main page, it works, but on other pages, Wicket adds a "../" in the action attribute, which seems to be meant well but is not what I want.
I'm using Wicket 1.4.17. How can I stop or change this behaviour?
The form is meant to enable the user to submit a short message as feedback to the site admin. It appears on every page and the input is collected from the PageParameters in the constructor of my pages' base class. If there is a more Wicket way to do this, I'll appreciate hints, but this should be a) stateless and b) very very simple.
I'd go the Wicket way and write a component for your feedback form which is then inserted into every page. As you have an (abstract) base class for all of your pages, you can simply add it there and it will appear on every page.
In your feedback form component, simply overwrite the onSubmit() method and send the message to the site admin.

Categories