Rendering a form based on bean field value - forms

I want to ask user to input password before submitting a file. So <h:panelGroup> should be rendered after hit the Submit button. But, <h:panelGoup> never be rendered.
test.xhtml
<ui:define name="body">
<h:form id="uploadForm" enctype="multipart/form-data">
<table>
<t:inputFileUpload id="uploadedFile" storage="file"
value="#{UpdateBean.uploadedFile}"/>
<h:commandButton value="Submit" action="#{UpdateBean.submit()}"/>
</table>
</h:form>
<h:panelGroup id="checkPassword" rendered="#{UpdateBean.submitIsPerformed}">
<h:outputText id="message" value="${UpdateBean.message}" />
<h:inputText id="password" value="#{UpdateBean.password}" />
<h:commandButton value="submit" action="#{UpdateBean.submitPassword()}"/>
</h:panelGroup>
</ui:define>
UpdateBean.java
#ManagedBean(name = "UpdateBean")
#SessionScoped
public class UpdateBean {
protected boolean submitIsPerformed = false;
protected String password = "";
protected String message = "Input your password ";
// omit getter and setter
public void submit() {
this.setSubmitIsPerformed(true);
System.out.println(submitIsPerformed); // output is true
while(true) {
if(password.equals("123")) {
break;
}
}
// then process uploadedFile
}
public void submitPassword(){
if(password.equals("123")) {
message = "Password confirmed !";
} else {
message = "Password is wrong !";
}
}
}

Your mistake is in the submit() method:
while(true) {
if(password.equals("123")) {
break;
}
}
The while(true) prevents the action method from returning. As long as the action method doesn't return, the server won't return the HTTP response with the updated view. Effectively, one of your server's CPU is stuck into 100% and the client is infinitely waiting for HTTP response. You should have noticed it by checking the browser's progress indicator, if it has one.
You should basically immediately return after toggling the boolean:
public void submit() {
submitIsPerformed = true;
}
And perform the password checking and upload file saving in submitPassword() method. However, as this isn't in the same form, the uploaded file will get lost. Even if you put it in the same form, it would be uploaded twice. But that's a different problem. I suggest to do the job the other way round.

Follow the suggestion from #BalusC, this is my updated code.
test.xhtml
<ui:define name="body">
<h:form>
<h:commandButton value="Upload a file" action="#{UpdateBean.submit()}">
<f:ajax render=":checkPassword" />
</h:commandButton>
</h:form>
<h:form id="checkPassword" styleClass="toggle" rendered="#{UpdateBean.submitIsPerformed}">
<table>
<tr>
<td><h:outputText value="Password" /></td>
<td><h:inputText id="password" value="#{UpdateBean.password}" /></td>
<td>
<h:commandButton value="Submit" action="#{UpdateBean.submitPassword()}">
<f:ajax execute="password" render=":uploadFile" />
</h:commandButton>
</td>
</tr>
</table>
</h:form>
<h:form id="uploadFile" enctype="multipart/form-data"
styleClass="toggle" rendered="#{UpdateBean.uploadFileIsPerformed}">
<t:inputFileUpload id="uploadedFile" storage="file"
value="#{UpdateBean.uploadedFile}">
</t:inputFileUpload>
<h:commandButton value="Submit" action="#{UpdateBean.uploadFile()}" />
</h:form>
</ui:define>
UploadBean.java
public String submit() {
setSubmitIsPerformed(true);
return "SUCCESS";
}
public String submitPassword(){
if(password.equals("123"){
setUploadFileIsPerformed(true);
setSubmitIsPerformed(false);
}
return "SUCCESS";
}
public String uploadFile(){
return "SUCCESS";
}

Related

JSP form pass parameter

In my jsp I am calling a servlet:
<form method="GET" action ="${pageContext.request.contextPath}/CurrencyController?action=listCurrency">
Currency code: <input type="text" name="currencyCode" id="currencyCode" />
<br />
<input type="submit" value="Search" />
</form>
But in my Servlet request.getParameter("action") is null. So how can I pass the action parameter?
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
if (action.equalsIgnoreCase("delete")){
String currencyCode = request.getParameter("currencyCode");
...
} else if (action.equalsIgnoreCase("edit")){
String currencyCode = request.getParameter("currencyCode");
...
} else if (action.equalsIgnoreCase("listCurrency")){
request.setAttribute("currencies", dao.getCurrencyByCode(request.getParameter("currencyCode")));
} else {
forward = INSERT_OR_EDIT;
}
RequestDispatcher view = request.getRequestDispatcher(forward);
view.forward(request, response);
}
You can define another hidden parameter like this
<input name="action" type="hidden"
value="${pageContext.request.contextPath}/CurrencyController?
action=listCurrency" />
and then in servlet use the same code request.getParameter("action") to get its value.

Checking which submit button was clicked

I am devoloping a web application using J2EE and Spring Roo as framework.
I want to create a form with two submit buttons:
One for save and continue
Another for save and finish
<form action="mycontroller" method="post">
<input type="submit" value="Save and continue"/>
<input type="submit" value="Save and finish"/>
</form>
So I can choose to either store the data in the database and add more entries or to store the data and finish the process.
How can I check what submit button was clicked in the method of the controller that processes the action?
public class MyController {
void actionMethod(...) {
// check which submit was clicked
}
}
You should add a name field to both buttons:
<input type="submit" name="button" value="Save and continue"/>
<input type="submit" name="button" value="Save and finish"/>
Once in the controller, you can recover the element by this name field and check its value field:
String field = request.getParameter("button");
if ("Save and continue".equals(button)){
// Do stuff
}
else if ("Save and finish".equals(button)){
// Do a different stuff
}
else {
// None of them were pressed
}
Or also you can use a different name value for both buttons:
<input type="submit" name="button1" value="Save and continue"/>
<input type="submit" name="button2" value="Save and finish"/>
In your controller:
String button1 = request.getParameter("button1");
String button2 = request.getParameter("button2");
if (button1 != null){
// Do stuff
}
else if (button2 != null){
// Do a different stuff
}
else {
// None of them were pressed
}
Second solution is preferred because it doesn't depend on the value of the elements
To reduce if-else if you can, and benefit from Spring framework to handle these mapping, try the following solution (if you don't have many meta parameters to send in the form):
<form action="AddToCartListController" method="post">
<input type="submit" value="Save and continue"/>
</form>
<form action="CommitCartListController" method="post">
<input type="submit" value="Save and finish"/>
</form>
...
public class CartListController {
void AddToCartListController(...) {
// business code
}
void CommitCartListController(...) {
// business code
}
}
// ... or ...
public class AddToCartListController {
void actionMethod(...) {
// business code
}
}
public class CommitCartListController {
void actionMethod(...) {
// business code
}
}
and define a proper mapping in Spring configuration.

JSF FacesMessage will not be renderd

I already read a lot of guides how to add a FacesMessage but nothing worked and i do not understand why?
I always get the following warning, but I do not now how to fix it?
[Warnung ] There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are:
- Login failed
My JSF View:
<!-- Login Form -->
<h:form id="loginForm" role="form" style="width: 400px; margin:0 auto;">
<div class="required-field-block">
<h:outputLabel for="email" value="Email-Adresse"></h:outputLabel>
<h:inputText id="email" label="Email" value="#{loginBean.email}" class="form-control" required="true" requiredMessage="Keine Mailadresse angeben"></h:inputText>
<h:message for="email" class="text text-danger"></h:message>
</div>
<div class="required-field-block">
<h:outputLabel for="password" value="Passwort"></h:outputLabel>
<h:inputText id="password" label="Passwort" value="#{loginBean.password}" class="form-control" required="true" requiredMessage="Kein Passwort angegeben"></h:inputText>
<h:message for="password" class="text text-danger"></h:message>
</div>
<h:commandButton id="sendLogin" update="loginForm" value="Login" type="submit" actionListener="#{loginBean.login}" class="btn btn-primary"></h:commandButton>
<h:message globalOnly="true"></h:message>
</h:form>
And my code from the bean:
public String login() {
UserManagement man = new UserManagement();
try {
user = man.getUserByEmail(this.email);
} catch (SQLException | IndexOutOfBoundsException e) {
String msg = "Login failed";
addErrorMessage(msg);
return "loginFailed";
}
if(this.user!=null&&this.user.getPassword().equals(password)) {
this.loggedIn = true;
return "loginSucceed";
}
else {
String msg = "Unvalid Password";
addErrorMessage(msg);
return "loginFailed";
}
}
private void addErrorMessage(String msg) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage fm = new FacesMessage(msg);
context.addMessage(null, fm);
}
What am i doing wrong? Why the hell is this message not renderd? I am a bit desperated because I tried everything with ID, globally but nothing worked and I am stumped why it does not work. Maybe it is just a dumb mistake i have not seen all the time :(
The h:message component renders only a single message from a component you have to refere to using the for attribute.
If you want to render ALL message, just use h:messages instead:
<h:messages/>
This should work fine for your usecase.

Show message of confirmation

I want to display a message to confirm creation of a group but I cannot diplay it.
group.xhtml:
<h:form id="grp">
<h:panelGrid columns="2">
<h:outputText value="Titre:"></h:outputText>
<p:inputText value="#{gpeBean.titre}"></p:inputText>
<p:commandButton id="btn_save"
value="Créer"
actionListener="#{gpeBean.test}">
</p:commandButton>
</h:panelGrid>
</h:form>
</center>
</h:panelGrid>
<h:form id="cr" rendered = "#{gpeBean.created}">
<h:outputText value="#{gpeBean.message}"/>
</h:form>
my bean :
#ManagedBean(name = "gpeBean")
#RequestScoped
public class GroupeBean implements Serializable{
GroupDAO daoGrp = new GroupDaoImpl();
UserDAO dao = new UserDaoImpl();
private String titre;
public String message = "";
private boolean created = false;
public String test(ActionEvent event){
Groupe p = new Groupe();
p.setTitre(this.titre);
daoGrp.Nouveau_groupe(p);
created = true;
this.setMessage("Groupe crée!");
return "p1";
}}
when I click button to execute method test, message is not displayed.
You use #ViewScoped in your bean.
Xhtml:
<h:form id="grp">
<h:panelGrid columns="2">
<h:outputText value="Titre:"></h:outputText>
<p:inputText value="#{gpeBean.titre}"></p:inputText>
<p:commandButton update=":grp:cr" id="btn_save"
value="Créer"
actionListener="#{gpeBean.test}">
</p:commandButton>
</h:panelGrid>
<p:outputPanel id="cr">
<h:outputText rendered="#{gpeBean.created}" value="#{gpeBean.message}"/>
</p:outputPanel >
</h:form>

spring mvc multiple form on jsp

Hello guys is it possible to have multiple forms on single jsp and also with a single button?
Here is my jsp page where i hava two forms, i know this way it is, it only save the second form.
<html>
<head>
<title>Update General Info</title>
<script type="text/javascript">
function validateForm()
{
var name=document.getElementById("name").value;
var surname=document.getElementById("surname").value;
var email=document.getElementById("email").value;
var amka=document.getElementById("amka").value;
if (name.length == 0)
{
alert("Name must be filled out");
return false;
} else if(surname.length == 0){
alert("Surname must be filled out");
return false;
}else if(email.length == 0){
alert("Email must be filled out");
return false;
}else if(amka.length == 0){
alert("Amka must be filled out");
return false;
}
}
</script>
</head>
<body>
<h1>Update General Info</h1>
<c:if test="${!empty user}">
<c:url var="saveArticleUrl" value="/articles/updateGeneralSave.html" />
<form:form onsubmit="return validateForm()" modelAttribute="user" method="POST" >
<table bgcolor="DBEADC" border=1>
<tr>
<th>Id</th>
<th>Team</th>
<th>Name</th>
<th>Surname</th>
<th>Username</th>
<th>Password</th>
<th>Email</th>
<th>AMKA</th>
<th>Status</th>
<th>Department</th>
</tr>
<tr>
<td><form:input readonly="true" path="id" value="${user.id}"></form:input></td>
<td><form:input readonly="true" path="team" value="${user.team}"></form:input></td>
<td><form:input id="name" path="name" value="${user.name}"></form:input></td>
<td><form:input id="surname" path="surname" value="${user.surname}"></form:input></td>
<td><form:input readonly="true" path="username" value="${user.username}"></form:input></td>
<td><form:input type="password" readonly="true" path="password" value="${user.password}"></form:input></td>
<td><form:input id="email" path="email" value="${user.email}"></form:input></td>
<td><form:input id="amka" path="amka" value="${user.amka}"></form:input></td>
<td><form:input id="status" path="status" value="${user.status}"></form:input></td>
<td><form:select path="department">
<c:forEach items="${departments}" var="dep">
<c:if test="${dep.dep_name==user.department }">
<OPTION selected VALUE="${dep.dep_name}"><c:out value="${dep.dep_name}"/></OPTION>
</c:if>
<c:if test="${dep.dep_name!=user.department }">
<OPTION VALUE="${dep.dep_name}"><c:out value="${dep.dep_name}"/></OPTION>
</c:if>
</c:forEach>
</form:select></td>
</tr>
</table>
</form:form>
</c:if>
<c:if test="${!empty phones}">
<c:url var="saveArticleUrl" value="/articles/updatePhoneSave.html" />
<form:form onsubmit="return validateForm()" modelAttribute="updatePh" method="POST" action="${saveArticleUrl}">
<table bgcolor="DBEADC" border=1>
<tr>
<th>Id</th>
<th>Phone</th>
<th>Mobile</th>
<th>Fax</th>
</tr>
<tr>
<td><form:input readonly="true" path="id" value="${phones.id}"></form:input></td>
<td><form:input id="phone" path="phone" value="${phones.phone}"></form:input></td>
<td><form:input id="mobile" path="mobile" value="${phones.mobile}"></form:input></td>
<td><form:input path="fax" value="${phones.fax}"></form:input></td>
</tr>
</table>
<input type="submit" value="Update" />
</form:form>
</c:if>
</body>
</html>
and the controllers
RequestMapping(value = "updateGeneral" , method = RequestMethod.GET)
public ModelAndView updateGeneral(#ModelAttribute("user") Users user ,#ModelAttribute("updatePh") Phone updatePh, #RequestParam("id")Integer id){
Map<String, Object> model = new HashMap<String, Object>();
model.put("user", articleService.getUser(id));
model.put("departments", articleService.listDepartments());
//twra mpike
model.put("phones", articleService.getPhones(id));
return new ModelAndView("updategeneral",model);
}
//evala akoma ena modelattri
#RequestMapping(value = "updateGeneralSave" , method = RequestMethod.POST)
public ModelAndView updateGeneralSave(#ModelAttribute("user") Users user){
articleService.updateUser(user);
return new ModelAndView("redirect:/articles/listusers.html");
}
#RequestMapping(value = "updatePhoneSave" , method = RequestMethod.POST)
public ModelAndView updatePhonesave(#ModelAttribute("updatePh") Phone updatePh){
articleService.updatePhone(updatePh);
return new ModelAndView("redirect:/articles/listusers.html");
}
You can have multiple forms in a JSP, but you can NOT send both at the same time.
You should mix both forms and both actions, retrieve all information in the action/controller and save phone and user information. Another options would be to use Ajax to send one of the form and send the other as usually.
By the way, your problem has nothing to do with Spring.
yes of courses, you can make your button to submit both your forms. But you have do it with ajax.
You need to loop through the forms on the webpage using document.forms[i] and with each form individually call the submit
Your only option is doing for ajax, you have to realize that if you Controller method will render a page after the first submit your second submit doing by HTTP will never take effect.
function submitForm(form, index){
$.ajax({
dataType: "json",
method: "POST",
url: "your controller url",
data:$('#form').serialize(),
success: function (data) {
if(index > 0){
submitForm(form+=1, index--)
}
}
});
}
You can do following trick like
Instead of sumbit button have only normal button as
<input type="button" value="Update" onClick="submit2forms();"/>
and on click of this button call below javascript method as
<script language="javascript">
function submit2forms() {
document.getElementById("form1").submit();
document.getElementById("form2").submit();
}
</script>