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.
Related
I've gone through dozens of articles, docs, and stack overflow questions (even the one with a similar intro)regarding the same issues but it still persists.
I've tried this with putting the functions in the .cshtml.cs page and on the .cshtml page, named and unnamed handler names, different framework for sending emails, and adding an empty action field in the form along with other fixes but the issue seems to be that the handler method itself is not firing while the form is submitting. Any and all help is appreciated and please let me know if more information is needed.
My HTML form:
<form method="POST" asp-page-handler="email">
<!-- Name input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientName" type="text" placeholder="Enter your name..." required/>
<label for="name">Full name*</label>
</div>
<!-- Email address input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientEmail" type="email" placeholder="name#example.com" required/>
<label for="email">Email address*</label>
</div>
<!-- Phone number input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientPhone" type="tel" placeholder="(123) 456-7890"/>
<label for="phone">Phone number</label>
</div>
<!-- Message input-->
<div class="form-floating mb-3">
<textarea class="form-control" name="clientMessage" type="text" placeholder="Enter your message here..." style="height: 10rem" required></textarea>
<label for="message">Message*</label>
</div>
<!-- Submit Button-->
<div class="d-grid"><button class="btn btn-primary btn-xl" type="submit" value="submit">Submit</button></div>
</form>
My functions as they are currently:
public void OnPostEmail()
{
var clientEmail = Request.Form["clientEmail"];
var clientName = Request.Form["clientName"];
var clientPhone = Request.Form["clientPhone"];
var clientMessage = Request.Form["clientMessage"];
sendEmail(clientEmail, clientName, clientPhone, clientMessage);
}
public void sendEmail(string clientEmail, string clientName, string clientPhone, string clientMessage)
{
var errorMessage = "";
try
{
// Initialize WebMail helper
WebMail.SmtpServer = "smtp.google.com";
WebMail.SmtpPort = 587;
WebMail.UserName = "***#gmail.com";
WebMail.Password = "MYPASSWORD";
WebMail.From = "***#gmail.com";
WebMail.EnableSsl = true;
// Send email
WebMail.Send(to: clientEmail,
subject: $"Request from: + {clientName}",
body: $"{clientMessage}\nPhone: {clientPhone}\nEmail: {clientEmail}"
);
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
}
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";
}
I am trying to post a form using dojo.xhrPost. Below code works fine in chrome but does not work at all in Firefox. When I say it doesn't work I see that page reloads again and nothing happens. I tried to use dojo.stopEvent(event); but doesn't seem to work in Firefox.
Can you please suggest me what could be my mistake. I feel the issue is more with the form than with xhrPost.
HTML Looks like below:
<div data-dojo-type="dijit/form/Form" data-dojo-id="myform" id="loginform"
encType="multipart/form-data" action="" method="post">
<script type="dojo/method" data-dojo-event="onSubmit">
if(this.validate()){
senddata(); //calling the javascript function
}else{
alert('Form contains invalid data. Please correct first');
return false;
}
return true;
</script>
<table cellspacing="10">
<tr>
<td><label for="name">Username:</label></td>
<td><input type="text" id="username" name="username"
required="true" placeholder="Your UserName" data-dojo-
type="dijit.form.ValidationTextBox"/></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td><input type="password" id="password" name="password"
required="true" placeholder="Your Password"
data-dojotype="dijit.form.ValidationTextBox"/></td>
</tr>
</table>
<div id="response" style="float: right"></div>
<button data-dojo-type="dijit.form.Button" type="submit" name="submitButton"
value="Submit" style="float: right;">Submit</button>
</div>
My Javascript code is below:
function senddata(){
dojo.stopEvent(event);
obj = {};
obj.user_name =dijit.byId("username").get("value");
obj.password =dijit.byId("password").get("value");
var xhrArgs = {
url: "./script/php/validatelogin.php",
postData: obj,
handleAs: "json",
load: function(data){
//alert('success');
if(data.success==true){
window.location = data.message;
dojo.byId("response").innerHTML = "Form posted.";
}else{
dojo.byId("response").innerHTML = "login Failed";
}
},
error: function(error){
console.log("error occured!!!");
dojo.byId("response").innerHTML = "Failed to Post the Form..";
}
};
//alert('starting');
var deferred = dojo.xhrPost(xhrArgs);
//alert('done');
return false;
}
First, change the data-dojo-type into path format. E.g.: dijit/form/ValidationTextBox
Second, fix your typing mistake in password field of data-dojo-type. You entered data-dojotype, missing the - b=in between 'dojo' & 'type'
More information about dojo.byId() & dijit.byId().
Here is the result:
<div data-dojo-type="dijit/form/Form" data-dojo-id="myform" id="loginform" encType="multipart/form-data" action="" method="post">
<script type="dojo/method" data-dojo-event="onSubmit">
if(this.validate()){
senddata(); //calling the javascript function
}else{
alert('Form contains invalid data. Please correct first');
return false;
}
return true;
</script>
<table cellspacing="10">
<tr>
<td><label for="name">Username:</label></td>
<td><input type="text" id="username" name="username" required="true" placeholder="Your UserName" data-dojo-type="dijit/form/ValidationTextBox" /></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td><input type="password" id="password" name="password" required="true" placeholder="Your Password" data-dojo-type="dijit/form/ValidationTextBox" /></td>
</tr>
</table>
<div id="response" style="float: right"></div>
<button data-dojo-type="dijit/form/Button" type="submit" name="submitButton" value="Submit" style="float: right;">Submit</button>
</div>
<script>
function senddata(){
dojo.stopEvent(event);
obj = {};
obj.user_name =dijit.byId("username").get("value");
obj.password =dijit.byId("password").get("value");
var xhrArgs = {
url: "./script/php/validatelogin.php",
postData: obj,
handleAs: "json",
load: function(data){
//alert('success');
if(data.success==true){
window.location = data.message;
dojo.byId("response").innerHTML = "Form posted.";
}else{
dojo.byId("response").innerHTML = "login Failed";
}
},
error: function(error){
console.log("error occured!!!");
dojo.byId("response").innerHTML = "Failed to Post the Form..";
}
};
//alert('starting');
var deferred = dojo.xhrPost(xhrArgs);
//alert('done');
return false;
}
</script>
I have following View:
#model DocuLive.ViewModels.InstallationRequestViewModel
#{
ViewBag.Title = "AttachDB";
Layout = "~/Views/Shared/_AdminPage.cshtml";
}
<h2>AttachDB</h2>
#using (Html.BeginForm("AttachDB","AppStart", FormMethod.Post)) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<p>Database DocuLive already exists on the server where you attempted installation. Do wish to attach existing DB to this installation of DocuLive? Details below will be used for this attempt.</p>
<fieldset>
<p>
<input type="submit" name="command" value="Attach" />
<input type="submit" name="command" value="Start over" />
</p>
<legend>DB server credentials</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.Server)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.Server)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.UserName)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserName)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.Password)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.Password)
</div>
</fieldset>
}
I have follownt two methods in controller:
public ActionResult AttachDB(InstallationRequestViewModel requestVM)
{
if (requestVM != null)
return View("AttachDB", requestVM);
else
{
TempData["Fail"] = "DocuLive database exist, but inicalization request has null value and cannot be used to attach DB";
return RedirectToAction("Index");
}
}
[HttpPost]
private async Task<ActionResult> AttachDB(InstallationRequestViewModel requestVM, string command)
{
try
{
switch (command)
{
case "Attach":
// do something complex and return RedirectToAction
case "Start over":
return RedirectToAction("Index");
default:
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
TempData["Fail"] = ex.Message;
return RedirectToAction("Index");
}
}
For some reason when i submit the form with either button, it hits the first method with no regard to fact that I explicitly specified FormMethod.Post for the form to make sure that submitting the form will take user to the second method that actually contains some business logic.
It is very strange because I am using similar approach all over the app and so far I had no issues with this.
Can anyone advise, why submitting the form with either button is considered Get instead of POST?
Thanks in advance...
Found it. I made the second method private by accident. Pretty stupid mistake...
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>