Primefaces messages "for" argument not working with bean validation - jsf

I have a bean validation according to:
#Min(value = 0)
#Max(value = 1000000)
private int kilometres;
In my facelet I have:
<p:messages autoUpdate="true" showDetail="true" showSummary="true" />
<p:outputLabel for="kilometres" value="Kilometres" />
<p:inputText id="kilometres" value="#{bean.vehicle.kilometres}">
<p:ajax event="change" />
</p:inputText>
When i have this it works fine, except that all messages for all field ids will be shown. I would like to specify for each field, like this:
<p:messages for="kilometres" autoUpdate="true" showDetail="true" showSummary="true" />
However, when I add the for="kilometres" option, then no validation messages is shown. Have I missed something or is it a bug?
Best regards

Use the <p:message/> component to show validation messages for each input component separately:
<p:outputLabel for="kilometres" value="Kilometres" />
<p:inputText id="kilometres" value="#{bean.vehicle.kilometres}">
<p:ajax/>
</p:inputText>
<p:message for="kilometres"/>
Showcase: AJAX - Validations
UPDATE
In order to show multiple message for a given component (with p:messages) you need to specify the relevant component ID in for="kilometres" and in your backing bean too:
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage("kilometres", new FacesMessage("Message 1"));
context.addMessage("kilometres", new FacesMessage("Message 2"));

Related

Primefaces messages for validation and growl for the rest

I have a JSF page with primefaces and I would like to use p:messages for the messages of the input validations and a Growl element for the rest of the things like notifications, errors ...
At the moment I have a Growl with attribute for and I'm sending notifications with this for attribute.
The problem is that I don't know which for attribute I have to put in the p:messages component. If I left it as null the notification messages are showing in Growl and on p:messages.
Here you can see an example of my JSF.
<p:growl id="growlNotifyNewReg" for="growlNotificationsNewRegister"
showSummary="true"
showDetail="true"
autoUpdate="true"/>
<h:outputText value="Validado"/>
<p:selectBooleanCheckbox id="checkValidado" value="#{}" required="true"/>
<h:outputText value="Temperatura (ÂșC)"/>
<p:inputText id="Temperatura" value="#{}" required="true">
<f:validateDoubleRange minimum="-50" maximum="60" />
<f:convertNumber maxFractionDigits="1" />
</p:inputText>
<!-- Other inputs... -->
<p:messages showSummary="true" showDetail="true" redisplay="false"/>
When I want to send a notification I do like this.
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "summary", "details");
FacesContext.getCurrentInstance().addMessage("growlNotificationsNewRegister", facesMsg);
This code sends messages to Growl component but also to messages component because it doesn't have for attribute. I want to know which attribute I have to put in messages component to show only the validations messages of the form.
As you can see I put redisplay attribute to false. Can I put multiple ids in the for attribute of the p:messages?
Here is an example works as you want, you can change it according to your code :
in .xhtml
<h:form prependId="false">
<p:growl id="growl" for="msg" showDetail="true" sticky="true" />
<p:panel header="Growl">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel for="msg" value="Message:" />
<p:inputText id="msg" value="#{growlView.message}" required="true" />
<p:outputLabel for="msg2" value="Message2:" />
<p:inputText id="msg2" value="#{growlView.message2}" required="true" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{growlView.saveMessage}" update="growl" />
</p:panel>
<p:messages id="messages" for="msg2" showDetail="true" autoUpdate="true" closable="true" />
</h:form>
in the for attribute for both <p:growl> and <p:messages> you can add whatever Ids you want just like for="id1 id2 .."
in bean
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
#ManagedBean
public class GrowlView {
private String message;
private String message2;
// setters / getters
public void saveMessage() {
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "summary", "details");
FacesContext.getCurrentInstance().addMessage("msg", facesMsg);
}
}

p:ajax not updating p:inputText

I am unable to update a <p:inputText> based on the value entered in another <p:inputText> using <p:ajax>. I am using JSF 2 with PrimeFaces 5. The second <p:inputText> is not updating, the listener associated with <p:ajax> is being called and i am getting the correct values in the listener but its not updated on the view.
the view code is:
<p:dialog id="newStdDlg" header="Add new Student" widgetVar="newStdDlg" modal="true">
<h:panelGrid id="newStdDlgPanel" columns="2" cellpadding="5" style="width:100%;">
<p:outputLabel value="First Name *" />
<p:inputText id="studentfname" value="#{addStudentBean.student.firstName}">
<p:ajax event="change" update="studentUsrname" listener="#{addStudentBean.firstNameChange}" />
</p:inputText>
<p:outputLabel value="Last Name *" />
<p:inputText value="#{addStudentBean.student.lastName}"/>
<p:outputLabel value="Father's Name *" />
<p:inputText value="#{addStudentBean.student.fatherName}"/>
<p:outputLabel id="uLbl" value="Username (System Generated) *" />
<p:inputText id="studentUsrname" value="#{addStudentBean.student.user.username}" />
<p:outputLabel value="This temporary password would be mailed to user: " />
<p:outputLabel id="stdpassword" value="#{addStudentBean.student.user.password}"/>
</h:panelGrid>
<p:commandButton value="Create Student"
actionListener="#{addStudentBean.addNewStudentAction}"
style="margin-left:auto;margin-right:auto;display:block;"/>
</p:dialog>
and the listener of the session scoped managed bean is :
public void firstNameChange() {
System.out.println("In AddStudentBean().firstNameChange()..........");
System.out.println("The value of student.getFirstName: "+student.getFirstName());
System.out.println("updating system generated username as: "+student.getFirstName()+String.valueOf(new UserDAO().getUserCount()+1));
student.getUser().setUsername(student.getFirstName()+String.valueOf(new UserDAO().getUserCount()+1));
student.getUser().setPassword(KaaloUtils.getPassword());
}
Like Jaqen mentioned in comments the comments use h:form inside dialog.
If you want to update the component from ManagedBean you can do that by using org.primefaces.RequestContext's update method.
RequestContext.getCurrentInstance().update("COMPONENT_ID_TO_UPDATE")
If you feel like this method is too Cohesive, you can update from Facelet only, make sure remember to not place p:dialog in a h:from instead use h:form inside p:dialog .

h:message doesn't display JSF message

In my JSF application, here's a simplified version of part of my form:
<h:form id="loginFormId">
<h:panelGrid columns="3">
<h:outputText value="Login :" />
<h:inputText label="Login" id="loginId" />
<rich:message for="loginId" ajaxRendered="true"/>
<f:facet name="footer">
<a4j:commandButton value="OK" action="#{authentifierUtilisateurBean.authentifierUtilisateur}">
<f:ajax execute="#form" render="#form" />
</a4j:commandButton>
</f:facet>
</h:panelGrid>
</h:form>
and here's a simplified version of my Managed Bean method authentifierUtilisateur() :
public String authentifierUtilisateur() {
try {
utilisateurEnBase = utilisateurDao.chercherParLogin( utilisateur.getLogin() );
}
...
if ( utilisateurEnBase == .... ) {
message = new FacesMessage(FacesMessage.SEVERITY_ERROR, bundle.getString("authentifier.utilisateur.login.inconnu"),"" );
FacesContext.getCurrentInstance().addMessage("loginFormId:loginId", message );
}
I'd like to assign an error to the rich:message tag associated with the h:inputText based on something happening in the authentifierUtilisateur() method.
A validator is not possible, because the method that will deliver results from the DB is run in the authentifierUtilisateur() method.
When I try the above code, the page doesn't display message in front of the h:inputText.
If I insert in the form, the code
<rich:messages />
(messages with an s) above the button as follows:
<f:facet name="footer">
<rich:messages />
<a4j:commandButton value="OK" action="#{authentifierUtilisateurBean.authentifierUtilisateur}">
<f:ajax execute="#form" render="#form" />
</a4j:commandButton>
</f:facet>
then I can see the message so I am sure that the server sends correctly message to the client.
So why the client doesn't display h:message in front of the h:inputText?
Is there something wrong in the Managed Bean?
addMessage("loginFormId:loginId", message)
A FacesMessage consists of a summary and a detail, rich:message will display the detail by default. That's the one you're leaving empty so there's nothing to display. Either fill in the detail or set #showSummary="true"
Insert an id to the h:panelGrid i.e
<h:panelGrid columns="3" id="grid">
Then in java code try this
FacesContext.getCurrentInstance().addMessage("loginFormId:grid:loginId", message );
Let me know if this helps

How to set JSF input field value before submit

I a have a JSF page with PrimeFaces with some input fields. Before a submit is done, I would like to use the value of a field as input for a method which does some calculations and updates another field with the result but without submitting the form.
This is the field that will be used as input for my method:
<h:outputLabel for="hiredate" value="#{msgs['addUser.hireDate']}" />
<p:calendar id="hiredate" value="#{userWizardMB.user.hireDate}" required="true" immediate="true"/>
<p:message for="hiredate" />
The calculation is done by clicking a <p:commandButton>:
<p:commandButton value="Calculate days" icon="ui-icon-circle-check" action="#{userWizardMB.calculateVacationDays}" update="vacationDays" process="#this" immediate="true"/>
And this is the method called:
public void calculateVacationDays() {
user.setVacationDays((int) vacationDaysCalculator
.calculateWithHireDate(user.getHireDate()));
}
When debugging, though, I see that this field is NULL even if I set value in the form.
How can I force the setting of this field - user.hireDate because I really need this value for my calculation?
Thank you
Edit: I removed all of the other fields in the form and the immediate attribute:
<h:form id="addUserForm">
<p:wizard widgetVar="wizard" flowListener="#{userWizardMB.onFlowProcess}">
<!-- TAB FOR PERSONAL DATA -->
<p:tab id="personal" title="#{msgs['addUser.personalTab']}">
<p:panel header="#{msgs['addUser.personalInformation']}">
<p:message for="vacationDays" showDetail="true" autoUpdate="true" closable="true"/>
<h:panelGrid columns="3" columnClasses="label, value" styleClass="grid">
<h:outputLabel for="hiredate" value="#{msgs['addUser.hireDate']}" />
<p:calendar id="hiredate" value="#{userWizardMB.user.hireDate}" required="true" />
<p:message for="hiredate" />
<h:outputLabel for="vacationDays" value="#{msgs['addUser.vacationDays']}"/>
<p:inputText id="vacationDays" value="#{userWizardMB.user.vacationDays}"/>
<p:commandButton value="Calculate days" icon="ui-icon-circle-check" action="#{userWizardMB.calculateVacationDays}" process="#this hiredate" update="vacationDays"/>
</h:panelGrid>
</p:panel>
</p:tab>
</p:wizard>
</h:form>
And the backing bean method is still not called.
Remove immediate="true" from the input and the command component. Do not use immediate unless you really understand what it should be used for. Further you also need to include the input component which you'd like to process in the update attribute of the command component. Note that this should represent the client ID, not the property name as mentioned in one of your comments.
<p:calendar id="hiredate" value="#{userWizardMB.user.hireDate}" required="true" />
...
<p:commandButton value="Calculate days" icon="ui-icon-circle-check"
action="#{userWizardMB.calculateVacationDays}"
process="#this hiredate" update="vacationDays" />
See also:
Why was "immediate" attribute added to the EditableValueHolders?
Use process="#form" (or process="[the id of the calendar component]" in the commandButton
process="#this" means that only the part of the model related to the commandButton (usually none) gets updated.
Old question, but did you add partialSubmit="true" in the commandButton tag? At least in PrimeFaces 3.5, false is the default value of this attribute (see the PrimeFaces PDF documentation).

JSF FacesContext#addMessage is not displayed

In my previous question I had the problem of displaying validation messages from a Login form. That issue is now solved, but this time I am not able to display a custom message with FacesContex#addMessage.
Using JSF + PrimeFaces.
<p:dialog header="Login" widgetVar="loginDlg">
<h:form id="loginForm">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText value="#{loginBean.username}" id="username" required="true" label="username" />
<p:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginBean.password}" id="password" required="true" label="password" />
<p:message for="password" />
<f:facet name="footer">
<p:commandButton value="Login" id="loginDlgButton" update=":loginForm,:welcomeMsg" actionListener="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
<p:message for="loginDlgButton" />
</f:facet>
</h:panelGrid>
</h:form>
</p:dialog>
In LoginBean (a SessionScoped ManagedBean):
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
RequestContext rContext = RequestContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(this.username, this.password);
rContext.addCallbackParam("loggedIn", true);
} catch (ServletException e) {
rContext.addCallbackParam("loggedIn", false);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials"));
}
}
This code, when validation succeeds and login fails, should display the "Invalid credential" message, but doesn't. Moreover, somewhere in the body of my web page, I have also added this line:
<p:messages autoUpdate="true" />
but my message isn't displayed even there.
Javadocs say that
If clientId is null, this FacesMessage is assumed to not be associated with any specific component instance
But I can't understand what this means.
place <p:messages autoUpdate="true" /> inside your form or inside some wrapper that is being updated by update of your commandButton , or place loginDlgButton instead of null in context.addMessage(...
I don't see a p:messages tag in your code. It is not the same as the p:message tag. p:message is attached to another component and is displayed as part of validation. The p:messages (or p:growl) component is what you are updating in your bean. Try adding a messages or growl component like this:
<h:form id="loginForm">
<p:growl id="messageGrowl" showDetail="true" sticky="false" />
<h:panelGrid columns="3" cellpadding="5">

Resources