form.submit() will trigger double inside a form - java

Good day,
The following is my jsp code:
<s:form beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" method="post" name="form1">
<!-- some others code here -->
<sx:row cssClass="button_row">
<sx:input name="updatePassword" image="submit"/>
</sx:row>
</s:form>
And this is my jquery:
<script type="text/javascript">
$(':input[name=updatePassword]').click(function() {
var answerProceed = confirm("Do you wish to proceed with the changes?");
if( answerProceed ){
var form = $("form[name=form1]");
form.attr("action", '<s:url beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" event="update"/>');
form.submit();
} else {
return false;}
});
</script>
We can see that, in the jQuery, it will trigger a update event to ChangePasswordAction.
However, currently I have a issue, which is sometimes it will trigger 2 times, its not always happen, but the happen rate is about 50%.
The following is the trigger log I get from my application log:
2019-06-26 18:19:13.658 [WebContainer : 31] TRACE o.s.w.c.s.XmlWebApplicationContext - [bmaker] - Publishing event in Root WebApplicationContext: org.springframework.security.event.authorization.AuthorizedEvent[source=FilterInvocation: URL: /common/change_password.html?update=&__stoken=1a47d3a9-29e8-4904-b204-3cb9fc0129f0]
2019-06-26 18:19:13.660 [WebContainer : 26] TRACE o.s.w.c.s.XmlWebApplicationContext - [bmaker] - Publishing event in Root WebApplicationContext: org.springframework.security.event.authorization.AuthorizedEvent[source=FilterInvocation: URL: /common/change_password.html?update=&__stoken=1a47d3a9-29e8-4904-b204-3cb9fc0129f0]
Anyone know what wrong with the code?

If an <input/> is of type="submit" in a form you have to use preventDefault() if you want to check for confirmation before you submit the form.
You can pass e as parameter in your listener as an Event implementation parameter like MouseEvent (because of the click event) in this case.
For example :
$(':input[name=updatePassword]').click(function(e) { // <-- e implements Event
e.preventDefault(); // <-- prevent the submit of the form
var answerProceed = confirm("Do you wish to proceed with the changes?");
if (answerProceed) {
var form = $("form[name=form1]");
// var form = e.currentTarget.form; you can do this
// var form = this.form; or you can do this, "this" is implicit clicked element
form.attr("action", '<s:url beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" event="update"/>');
form.submit();
}
else {
return false;
}
});
You can access the form of an element by doing .form on an element, see
HTMLSelectElement.form
See
Event.preventDefault()
Event
MouseEvent

Related

How to make variable set into a handler visible into another handler?

I have the following GetMapping handler:
#GetMapping("/auto-upgrade/{id}")
public String followJob(Model model, #PathVariable String id) {
boolean stopMessageAlreadyThere = model.asMap().containsKey("stopMessage");
if (!stopMessageAlreadyThere) {
model.addAttribute("stopMessage", null);
}
//do some stuff
return "dashboard";
}
In the dashboard.html that I return, I have the following form embedded:
<form action="#" th:action="#{/auto-upgrade/stop}" th:object="${stopRequest}" method="post" th:if="${#strings.toString(upgradeState.upgradeStatus) == 'RUNNING'}">
<input style="visibility: hidden" th:field="*{jobId}" th:value="${upgradeState.id}"/>
<p>Your mail address: <input type="email" id="stoppingEmail" oninput="saveLastInput()" th:field="*{userEmail}"></p>
<p><input type="submit" value="Request stop upgrade" />
</form>
... and then right after I have the following element:
<div th:if="${stopMessage != null}">
<p>Message for stop command: <b th:text="${stopMessage}"></b></p>
</div>
When I render the view, the stopMessage is null because it's me inserting it as such.
If I submit the form, I go through this PostMapping handler:
#PostMapping("/auto-upgrade/stop")
public String stopJob(#ModelAttribute StopRequest stopRequest, Model model) {
try {
//something that may fail
model.addAttribute("stopMessage", "Stop request accepted");
} catch (UpgradeNotRunningException | NotInGracePeriodException | StopUpgradeException e) {
model.addAttribute("stopMessage", "FAILED TO STOP: " + e.getMessage());
}
return "redirect:/auto-upgrade/" + stopRequest.getJobId();
}
So basically I'm always going to add a `stopMessage, whether successful or failing.
However, when I'm called back to my #GetMapping("/auto-upgrade/{id}") to which I redirect, the Model model is empty meaning that my value previously saved is not added.
I would have expected Model to be shared across handlers, but it doesn't look to be the case.
How can I retrieve the value of a property set into another handler? Is it possible with Thymeleaf ?
Note: for the time being, I have made stopMessage a field of my Controller class and I set it null / not null around the handlers so that I'm always able to see its value. It is a solution, but it doesn't seem to be the right way to do it. So since I'm new to Thymeleaf, I'd be happy to hear the proper way of handling such cases.
You need to use RedirectAttributes:
#PostMapping("/auto-upgrade/stop")
public String stopJob(#ModelAttribute StopRequest stopRequest,
Model model,
RedirectAttributes redirectAttributes) {
try {
//something that may fail
redirectAttributes.addFlashAttribute("stopMessage", "Stop request accepted");
} catch (UpgradeNotRunningException | NotInGracePeriodException | StopUpgradeException e) {
redirectAttributes.addFlashAttribute("stopMessage", "FAILED TO STOP: " + e.getMessage());
}
return "redirect:/auto-upgrade/" + stopRequest.getJobId();
}
That way, stopMessage is available after the redirect. (Note that if the user manually refreshes the page after the redirect, they are lost)
See https://www.baeldung.com/spring-web-flash-attributes for more info.

Wicket issue field value never used

Very new to Wicket but have very basic Java. I am not understanding how "result" is not been used as I have used it in an AjaxButton function
The quickfix says to provide a getter and setter, which I did (have removed now) but still nothing happened when I click the OK button
CalcPage.java:
public class CalcPage extends WebPage{
private int num;
private int result; // error:The value of the field CalcPage.result is not used
private Label r;
public CalcPage() {
Form<Void> f = new Form<Void>("f");
add(f);
f.add(new TextField<Integer>("num", new PropertyModel<Integer>(this, "num")));
AjaxButton ok = new AjaxButton("ok") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
result = 2 * num;
target.add(r);
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
}
};
f.add(ok);
r = new Label("r", new PropertyModel<Integer>(this, "result"));
add(r);
}
}
CalcPage.html
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8" />
<title>Apache Wicket Quickstart</title>
<link href='https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:regular,bold' rel='stylesheet' type='text/css' />
<link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Stylesheet" />
</head>
<body>
<form wicket:id="f">
<input type="text" wicket:id="num"/>
<input type="submit" value="OK" wicket:id="ok"/>
</form>
Result: <span wicket:id="r"></span>
</body>
</html>
Hoping (according to book Enjoying web development with Wicket) to double the input but when I click on OK and nothing happens.
Also in code I am getting a compile error with #Override, once this is removed I can compile and load webpage. Are they related??
Wicket Ajax Debug window info:
INFO: focus removed from
INFO: focus set on
INFO: focus removed from
INFO: focus set on wicketDebugLink
INFO: focus removed from wicketDebugLink
INFO: focus set on ok2
INFO: Received ajax response (69 characters)
INFO:
INFO: Response processed successfully.
INFO: refocus last focused component not needed/allowed
ETA I changed from private to public and that error is gone but clicking ok still doesn't work and new error has come:
The method onSubmit(AjaxRequestTarget, Form) from the type new AjaxButton(){} is never used locally
You need to call r.setOutputMarkupId(true) if you want to update a Component via Ajax.
1) if javac (or your IDE) says that #Override does not override anything then most probably you have a typo somewhere and you need to fix it, i.e. to properly override the method from super
2) never leave #onError() empty. As a minimum add some basic logging in it to notify you that there is a validation error. Maybe #onSubmit() is not called at all. The best would be to have a FeedbackPanel in the page and you should update it in #onError() - target.add(feedbackPanel)
3) Check the browser's Dev tools Console for JavaScript errors. I'd expect Wicket complaining that it cannot find an HTML element with id rXY (where XY is a number) because of the missing r.setOutputMarkupId(true)
Version 8 of wicket doesn't have the "form" parameter so it can be deleted:
new code
AjaxButton ok = new AjaxButton("ok") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
result= 2*num;
target.add(r);
}

Form with prefilled data

I have a form for a new staff to fill in. But now, I want to have a edit form which return the form that user has filled.
This is my controller:
public static Result updateForm(String id) {
Form<staffInfo> existingStaffForm = Form.form(staffInfo.class);
staffInfo existingStaff = staffInfo.find.byId(id);
return ok(
views.html.update.render(existingStaffForm.fill(existingStaff))
);
}
This is my scala.html:
#(existingStaffForm: Form[staffInfo])
#import helper._
#implicitField = #{ FieldConstructor(myFieldConstructorTemplate.f) }
#main("Employment application") {
#form(routes.Application.newForm(), 'class -> "form-horizontal") {
<div class = "row">
<div class="col-md-6">#inputText(existingStaffForm("fullName"), 'size->50,'_label -> "Full name:", '_help -> "*", '_showConstraints -> false)</div>
<div class="col-md-6">#select(
existingStaffForm("sex"),
options(Seq("Male", "Female")),
'_label -> "Sex:")</div>
</div>
}
}
When I run on my browser, it return error [RuntimeException: Cannot fill a form with a null value].
At the controller on line -> return ok.
UPDATE
I've found out the main problem! I have a 'Update' button on the display page for the user to click (if they want to update their info), which the button will be directed to edit form page (the code is above). Here is code for the 'Update' button:
<input type="button" class="btn btn-default" value="Update">
And my routes:
GET /staff/:id/update controllers.Application.updateForm(id:String)
I think, the problem is at the href tag. Can someone help how to put the link in the correct way?
Apparently existingStaff is null, debug it somehow. i.e.:
public static Result updateForm(String id) {
Form<staffInfo> existingStaffForm = Form.form(staffInfo.class);
staffInfo existingStaff = staffInfo.find.byId(id);
if (existingStaff==null) {
return badRequest("Oooops existingStaff not found in DB... ");
}
return ok(
views.html.update.render(existingStaffForm.fill(existingStaff))
);
}
BTW: By the convention class name of the model should start with upper case: StaffInfo
You should generate your a href using reverse routing.
#routes.WhateverYourControllerIsNamed.updateForm("id")
see http://www.playframework.com/documentation/2.1.1/ScalaRouting

JQuery - Ajax - Struts2 list

Im looking for a little help on getting my JQuery/Ajax call to return a List from a Struts action and populate a DIV with the list elements using s:iterator.
I have the following JQuery
function lookupCustomerJs() {
alert("lets start");
$.ajax({
type: "POST",
url: "lookupCustomerAjax",
data: $('#lookupCustomer').serialize(),
success:function(response) {
alert("do stuff");
$('div#custList').replaceWith($(response).find("div#custList"));
},
failure:function(response) {
alert('Ajax call failed');
},
error:function(response) {
alert(exception);
}
});
}
I have a DIV within my page which I then want to iterate the list through
<div id="custList">
<s:iterator status="stat" value="customerList" var="customer">
<s:param name="custFName" value="%{customer.firstname}" />
</s:iterator>
</div>
And my Action method which IS called, because when I debug, the debugger goes through the code.
private List<Customer> customerList;
public String lookupCustomerAjax() {
dummyData();
return SUCCESS;
}
This successully calls my Action method, but all I get is the "lets start" alert, then nothing else, no errors, nothing!
So I'm guessing it's just the jQuery/Ajax success:function(response) { not fireing correctly, but can't see why.
It is probably the "lookupCustomerAjax" is an invalid url or file name. You should try adding the extension.
Also, for troubleshooting, you should console.log(response) in your succession to see that you are actually get the result.

jQuery form Submit not working in JSF?

I have a JSf form, I am tryin' to use jQuery Ui dialog plugin to submit the form.
here's the code snippet.
function confirmSubmit() {
$('#dialog').dialog('open');
return false;
}
$('#dialog').dialog({
autoOpen : false,
width : 400,
modal : true,
resizable : false,
buttons : {
"Submit Form" : function() {
document.myForm.submit();
},
"Cancel" : function() {
$(this).dialog("close");
}
}
});
<h:form id="myForm">
<h:commandLink action="#{Bean.search}" type="submit" onclick="return confirmSubmit()" id="search" styleClass="buttonSearch">
</h:commandLink>
The "document.myForm.submit();" part in the dialog box isn't working i.e., no calls goes to the server and in the server console I see the error:
11:45:32,738 SEVERE [lifecycle]
JSF1054: (Phase ID: RENDER_RESPONSE 6,
View ID: /PRT01/IMCM0101.jsp)
Exception thrown during phase
execution:
javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl#ec333b]
The dialog box is appearing correctly but once i press the submit button "document.myForm.submit();" code is executed and the form is NOT submitted instead the above described error comes on the server console.
as you return false; it won't submit actually.
To make dialog working
$(document).ready(function() {
var $dialog = $('<div></div>')
.html('This dialog will show every time!')
.dialog({
autoOpen : false,
width : 400,
modal : true,
resizable : false,
buttons : {
"Submit Form" : function() {
document.myForm.submit();
},
"Cancel" : function() {
$(this).dialog("close");
}
}
});
});
and then just call
function confirmSubmit() {
$dialog.dialog('open');
return false;
}
It's done, some JSF parameters were missing. which jsf adds during form submissiom, I added them using jQuery:
$("a[id$='search']").click(function() {
var input = $("<input>").attr("type", "hidden").attr("name", "myForm:search").val("myForm:search");
$('#myForm').append($(input));
$("p#dialog-email").html(titleVar);
$('#dialog').dialog('open');
});

Categories