I have a JSF 2.1 + PrimeFaces 3.3 page:
<h:form id="particluar">
<p:message id="msg" globalOnly="true" display="text"/>
<h:panelGrid columns="2" id="test">
<h:panelGrid id="panel2" columns="3">
<p:inputText id="name1" value="Student.studentID" required="true"/>
<p:commandButton value="Check Name" actionListener="#{Student.abc}" process="name1" update="panel2" />
<p:message id="msg1" for="name1" display="text"/>
</h:panelGrid>
<p:inputText id="name2" required="true"/>
<p:message id="msg2" for="name2" display="text"/>
<p:inputText id="name3" required="true"/>
<p:message id="msg3" for="name3" display="text"/>
</h:panelGrid>
<p:commandButton value="submit" actionListener="#{Student.xyz}" update="particluar" />
</h:form>
I'm trying to manually add faces messages when the name is invalid:
public void xyz() {
if (name1.equals("primefaces")) {
FacesContext.getCurrentInstance().addMessage("msg1", new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Name", "Invalid Name"));
}
if (name2.equals("primefaces")) {
FacesContext.getCurrentInstance().addMessage("msg2", new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Name", "Invalid Name"));
}
if (name3.equals("primefaces")) {
FacesContext.getCurrentInstance().addMessage("msg3", new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Name", "Invalid Name"));
}
}
But they do not show up and the server log keeps printing the following warning:
There are some unhandled FacesMessages, this means not every
FacesMessage had a chance to be rendered
How do I show them in the page?
And, a second question, if I submit the form with three empty input fields, it shows "required input error message" in each <p:message> associated with the <p:inputText>. How do I show them in the <p:message globalOnly="true">?
How do I show them in the page?
You need to specify a valid client ID. The client ID is not the same as component ID. The client ID is whatever you see in the JSF-generated HTML output. Also, the client ID should be the one of the input component, not of the message component.
So, given a
<h:form id="particular">
<p:inputText id="name1" />
<p:message id="msg1" for="name1" />
</h:form>
the input component has the client ID particular:name1 (rightclick page in browser and do View Source to see it yourself). So, the message should be attached on exactly this client ID.
context.addMessage("particular:name1", message);
And, a second question, if I submit the form with three empty input fields, it shows "required input error message" in each <p:message> associated with the <p:inputText>. How do I show them in the <p:message globalOnly="true">?
The <p:message> is not the valid component for that, you should use <p:messages>.
<p:messages id="msg" globalOnly="true" display="text"/>
The globalOnly="true" attribute means that only messages with a null client ID will be shown. So, you should just add exactly such a message.
context.addMessage(null, message);
See also:
How to use JSF h:messages better?
When and how is clientID generated in JSF?
Unrelated to the concrete problem, the non-global messages ("Invalid name") which you're trying to add there should actually be done by a fullworthy validator. See also How to perform validation in JSF, how to create a custom validator in JSF for a concrete example.
Related
I need your assistant in showing the error messages in the proper messages component. In the form, I am using the messages component tag twice. The first messages component tag which is called messages, I am showing any error to the user that is validated from the main form.
Where I am also having a dialog in the same form that will validate if a variable is blank or empty, if it is blank,the error message should be shown in the messagesPDFST which is in the dialog not in the main form. Currently any error it is shown in the first messages component which is messages even if the error is in the dialog. Here is the code:
<h:form id="Requests">
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true"/>
<p:dialog id="Certificate1" header="Certificate" widgetVar="Certificate1" modal="true">
<div align="right">
<p:messages id="messagesPDFST" showDetail="true" autoUpdate="true" closable="true" />
<p:commandButton value="Download" ajax="false" actionListener="#{hrd.PDFSTAR}" >
<p:fileDownload value="#{hrd.fileSTAR}" />
</p:commandButton>
</div>
</p:dialog>
</h:form>
and the Bean Code:
public void PDFSTAR() {
if (refNo== null || refNo.equals("")) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!", "Please enter the Reference No."));
}
}
To display a FacesMessage for a specific component, you first need to
Queue the message, for the specific component:
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!", "Please enter the Reference No."));
The first argument where you have null, is where you should have the client-side id of the component you're looking to target
Specify the for attribute on the message component, limiting display of messages to that component only.
Putting it all together, you should now have
FacesContext.getCurrentInstance().addMessage("Requests:Certificate1:downloadButton", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!", "Please enter the Reference No."));
Where "downloadButton" is the id of the <p:commandButton/>
<p:messages for="downloadButton" id="messages" showDetail="true" autoUpdate="true" closable="true"/>
<p:commandButton id="downloadButton" value="Download" ajax="false" actionListener="#{hrd.PDFSTAR}" >
<p:fileDownload value="#{hrd.fileSTAR}" />
</p:commandButton>
Unrelated to the actual problem
There's no need to be using <p:messages/> in the dialog, if the message is to be displayed for a single component only - <p:message/> will work just as well
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
I have a field that has a required attribute. When I press the Accept button to save some data without entering any value in the field, an error message is displayed. So far so good.
But, if right after that I decide to click on the Cancel button, that error message overrides the confirmation message that is supposed to be displayed inside a <p:dialog/> element.
NOTE: If instead I use the <p:confirmDialog/> component, there seems to be no problem because, I guess, it uses a message="" attribute, no the <p:messages/> tag.
XHTML
<p:dialog>
<p:outputPanel>
<h:form>
<h:outputText value="Field:"/>
<p:inputText id="field" value="" type="text" required="true" requiredMessage="You must complete the field" />
<p:growl id="messages" showDetail="true"/>
<p:commandButton id="dialogCancel" value="Cancel" oncomplete="confirmCancelDialog.show();" actionListener="#{controller.addCloseWarn}" />
</h:form>
</p:outputPanel>
</p:dialog>
<h:form>
<p:dialog id="confirmCancelDialog" header="Warning!" widgetVar="confirmCancelDialog" modal="true" >
<p:messages id="closeMessage" showDetail="true" autoUpdate="true" />
<p:commandButton id="confirm" value="Accept" onclick="..." />
<p:commandButton id="decline" value="Cancel" onclick="..." />
</p:dialog>
</h:form>
Bean controller
public void addCloseWarn(ActionEvent actionEvent) {
FacesContext.getCurrentInstance().addMessage("closeMessage", new FacesMessage(FacesMessage.SEVERITY_WARN, null,
"Are you sure you want to leave the page?"));
}
Problem with Cancel button is that your form is submitted and validation is executed. You can add process="#this" attribute to commandButton, so other parts of form will not be processed and your addCloseWarn method will be executed.
I would also add that this is probably not standard use of message tag. It is used to show errors, warning and successful messages, not confirmation questions. So use confirmDialog or use standard dialog with just ordinary text and OK - Cancel buttons.
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"));
So my team has a jsf and we use an EL statement to read in the value of an input box, works fine but by default we have our value set as what should be filled into the field. How can I set a default value for the input while still having the EL statement work.
Example:
<h:inputText value="#{registrationBean.firstName}" styleClass="formEle"/>
I tried
<h:inputText value="#{registrationBean.firstName}First Name" styleClass="formEle"/>
but this breaks the connection when we submit.
Any ideas?
You're looking for something which is called a "watermark" or "placeholder". At low level, these days this is normally to be done by the HTML5 placeholder attribute:
<input type="text" placeholder="First Name" />
This works of course only in browsers supporting HTML5 and then only with JSF components supporting the new HTML5 attribute. The standard JSF <h:inputText> doesn't support this natively (yet). You'd need to look for 3rd party component libraries supporting this. Among them is PrimeFaces with its <p:watermark>:
<h:inputText id="firstName" value="#{registrationBean.firstName}" />
<p:watermark for="firstName" value="First Name" />
If using PrimeFaces is not an option for some reason, you'd need to reinvent it yourself in flavor of a custom component and/or a custom piece of JS/jQuery, exactly like <p:watermark> is doing under the covers.
You could define default value of <h:inputText> in your backing bean in PostConstrut phase.
#ManagedBean(name="registrationBean")
public class RegistrationBean{
private String firstName;
#PostConstruct
public void init(){
firstName = "your default value";
}
}
After page creation value displayed in h:inputText will be as you defined in backing bean.
It's kind of work around without any third party library maybe it will help someone.
The HTML-Tags rendered by JSF can be modified by JavaScript after loading inserting a placeholder attibute for HTML5:
<script>
window.onload = function() {
document.getElementById('email').setAttribute("placeholder", "Email");
document.getElementById('pwd').setAttribute("placeholder", "Password");
}
</script>
If you decide to use PrimeFaces you are not required to use a watermark, see example below:
<h:form>
<p:panel id="panel" header="Client Details" style="margin-bottom:10px;">
<p:messages id="messages" />
<h:panelGrid columns="2">
<h:outputLabel for="firstName" value="First Name" />
<p:inputText id="firstName" value="#{clientlistpagebean.selectedFieldClient.firstName}" required="true" />
<p:outputLabel for="lastName" value="Last Name" />
<p:inputText id="lastName" value="#{clientlistpagebean.selectedFieldClient.lastName}" required="true" />
</h:panelGrid>
</p:panel>
<p:commandButton value="Submit" update="panel" style="margin-right:20px;" />
</h:form>