I am not clear on how addMessage() and FacesMessage works. If I didnt specify a <h:message> for it to display a message, the summary message will be displayed. But if I create a <h:message> field for it, the detailed message will be displayed. Why? How to select which message to display? Below is my code:
Bean
public String login()
{
if(password.equals("123123"))
{
session.setAttribute("username", username);
return "home";
}
else
{
FacesContext.getCurrentInstance().addMessage("loginForm", new FacesMessage(FacesMessage.SEVERITY_WARN,"Incorrect Username and Passowrd", "Please enter correct username and Password"));
return "login";
}
}
JSF
<h:form id="loginForm">
<h:outputLabel for="username" value="Username: " />
<h:inputText id="username" value="#{loginBean.username}" required="true" requiredMessage="Username is required" />
<h:message for="username"></h:message>
<br /><br />
<h:outputLabel for="password" value="Password: " />
<h:inputSecret id="password" value="#{loginBean.password}"></h:inputSecret>
<h:message for="password"></h:message>
<br /><br />
<h:commandButton action="#{loginBean.login()}" value="Login"></h:commandButton>
<br /><br />
</h:form>
The code above will produce the following output:
But if I add <h:message for="loginForm"></h:message> into my code, the output will be:
It shows the detailed message instead of summary message, it is not a big deal actually but I just want to know why this happens? Can anyone explain?
That orange message will only appear when you have javax.faces.PROJECT_STAGE set to Development and you forgot to declare a <h:messages> in the view. In such case JSF can't show the message anywhere in the page. Normally, this is only logged as a warning in server log like so:
There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered
However, for developer's convenience this is also appended to the end of the webpage when project stage is set to development. But you should not rely on that as normal functionality of the webapp. You should take that as a hint that you overlooked something or did something wrong. The correct solution would be to add an appropriate <h:message for="xxx"> or at least a <h:messages> as fallback.
That the development stage message shows the summary instead of the detail is your least concern. It should in first place not have been displayed at all.
See also:
How to use JSF h:messages better?
Related
I'm new to JSF, my question may be silly for you.. It is very much valuable for me..
<h:form id="form1">
<p:messages autoUpdate="true" showDetails="true" />
<p:dataTable id='form1ID'>....</dataTable>
<p:inputText value="#{bean.name}" required="true"
requiredMessage="Please Enter Name!" label="Name ">
</p:inputText>
</h:form>
<h:form id="form2">
<p:messages autoUpdate="true" showDetails="true" />
<p:dataTable id='form2ID'>....</dataTable>
<p:inputText value="#{bean.name}" required="true"
requiredMessage="Please Enter Name!" label="Name ">
</p:inputText>
<p:commandButton value="Submit" update=":form1:form1ID"
actionListener="#{mgmtBean.doCreateType}" />
</h:form>
I have two forms. when I click on form2 command button with empty fields, it will show error messages perfectly since i have added <p:messages autoUpdate="true" showDetail="true"/>.
The bad thing or surprising thing here for me is, it is showing error messages on top of form1 also may be because of <p:messages autoUpdate="true" showDetail="true"/> added in form1 and i'm trying to update form1 on command button click in form2.
I don't want to show error messages on form1 when form2 is throwing validation error messages. How can i fix this ? I googled it out.. but couldn't find the solution.
Evironment i'm using is jsf-api-2.1.5 and primefaces 4.0 version and view technology is facelets(XHTML)
Hope it is clear..
Any idea is highly appreciated.
Try to disable rendering of messages on the form1:
<p:messages autoUpdate="true" showDetails="true" rendered="#{bean.renderedmessage}"/>
And in the bean, add the renderedmessage variable:
public Boolean getRenderedmessage() {
return renderedmessage;
}
/**
* #param renderedmessage the renderedmessage to set
*/
public void setRenderedmessage(Boolean renderedmessage) {
this.renderedmessage = renderedmessage;
}
And, for the doCreateType() method, add:
public void doCreateType(){
..............
setRenderedmessage(false);
.............
}
After the form1 is updated, you can choose some event or method, where you can setRenderedmessage(true);
What you're currently experiencing should indicate to you that you usually don't need two <p:messages/>s in the same JSF view; one is enough.
Regardless of the fact that you have two <h:form/>s on your page, there's still only one FacesContext associated with that view (The FacesContext object is a JSF construct that encapsulates all the information/data/components etc that's associated with a given JSF page request).
By default the <p:messages/> will display every FacesMessage that is queued within it's associated instance of FacesContext, regardless of the source of the message (well, almost: if you set globalOnly="true" on the <p:messages/>, you can change that behaviour).
That being said, you basically have two options:
Get rid of the extra <p:messages/> and rely on (and appropriately position) only one to display all errors/warnings for that view
Specify the for attribute, set to the desired component. Doing so, you'll guarantee that only one input component can trigger the display of its associated message component. For example
<h:form id="form1">
<p:messages for="inputName" autoUpdate="true" showDetails="true" />
<p:dataTable id='form1ID'>....</dataTable>
<p:inputText id="inputName" value="#{bean.name}" required="true"
requiredMessage="Please Enter Name!" label="Name ">
</p:inputText>
</h:form>
Note that I've set an id attribute on the <p:inputText/> component; this is necessary so you can use it in the for attribute for the messages component.
Further reading:
What is FacesContext used for?
I have fixed the issue by using the following code
<p:messages autoUpdate="true" showDetails="true" visibility="info"/>
so it is just displaying info messages and other pop up error messages will not be showun.
I have a h:form with several inputs and each of them got its own h:message and I'm looking for a way to show (using render or assigning some styleClass) some other element only when specific h:message is being shown (and hide when that h:message is not being displayed).
Here a code snippet
<li>
<h:panelGroup id="current_password_wrapper">
<p:password value="#{myBean.myCurrPass}" id="current_password" required="true"
styleClass="required_field" />
</h:panelGroup>
<h:message for="current_password"/>
</li>
<li>
<h:panelGroup id="new_password_wrapper">
<p:password value="#{myBean.myNewPass}" id="new_password" required="true"/>
</h:panelGroup>
<h:message for="new_password"/>
<h:commandLink value="my value"/>
</li>
I want to make the h:commandLink visible only when the <h:message for="new_password"/> is being displayed
So far I couldn't find anything...
If your environment supports EL 2.2, then you could check if FacesContext#getMessageList() isn't empty for the particular client ID.
<p:password binding="#{new_password}" ... />
<h:commandLink ... rendered="#{not empty facesContext.getMessageList(new_password.clientId)}" />
If the message is being shown as result of a validation error, then you could also just check the UIInput#isValid() state of the component associated with the message.
<p:password binding="#{new_password}" ... />
<h:commandLink ... rendered="#{not new_password.valid}" />
Note that manually adding a faces message to the context won't mark the input component invalid. Therefor either a true Validator should be used which throws a ValidatorException, or an explicit input.setValid(false) call has to be done programmatically.
I think with the answer to this question you requirement can be archived:
How to number JSF error messages and attach number to invalid component
I think you can do something like this:
<h:outputText value="output text" rendered="#{bean.messageIndexes['form:input1'] > 0}" />
<a4j:outputPanel id="tapalSectionSendToPanel" ajaxsingle="true">
<h:inputText id="sendToId1" value="#{MainBean.SectionBean.sendTo}"
class="createresizedTextbox"
required="true" requiredMessage="#{msg.labl_required}"
disabled="true" />
<h:message for="sendToId1" style="color:red" />
</a4j:outputPanel>
i need to validate textbox for empty validation and should show required when i click button without entering any value in textbox. It works fine without disabled="true". Whats the alternative for my requirement.
First, required and disabled don't go well together, because they are mutually exclusive as per the JSF Spec:
required: Flag indicating that the user is required to provide a submitted value for this input component.
disabled: Flag indicating that this element must never receive focus or be included in a subsequent submit.
Like I said in the comments, you can just display a message when the user tries to submit the form without selecting a node:
<h:inputText id="sendToId1" value="#{MainBean.SectionBean.sendTo}"
styleClass="createresizedTextbox" required="true" readonly="true" />
<h:message for="sendToId1" value="#{msg.labl_required}"
rendered="#{facesContext.postback and facesContext.validationFailed}" />
As an alternative you can just display a text anywhere in your markup:
<h:outputText value="#{msg.labl_required}"
rendered="#{empty MainBean.SectionBean.sendTo}" />
disabled="true" disables the input (so it's skipped when the form is submitted), if you don't want the user to type in it use readonly="readonly"
I have two forms in my page, in the first formulary are input fields with validation, and in the other a dataTable. The first formulary has a message area to show validation errors, and the second formulary has a message area to show problems with the retrieval of the data (this message area is updated from myController.search).:
<h:form id="form1">
<p:message id="messageForm1" for=":form1" />
<p:inputText id="text1" value="#{myBean.data}" required="true" />
....
<p:commandButton value="Search" actionListener"#{myController.search}"
update=":form2:dataTable :form2:messageForm2 :form1:messageForm1" process="text1, ..." />
</h:form>
<h:form id="form2">
<p:message id="messageForm2" for="messageForm2" />
<p:dataTable>
...
</p:dataTable>
</h:form>
The problem is that the messages in the form2 are working, but the validation messages in form1 are never shown
The description of the for attribute of the p:message tag says:
Id of the component whose messages to display.
So you can't specify the ID of the form. You have to specify the ID of a single form component. e.g. <p:message id="messageForm1" for="text1" />. But then you have to create one message element for every form component.
An alternative would be to use the p:messages tag. For examples see here: http://www.primefaces.org/showcase-labs/ui/messages.jsf
I am working on JSF2.0 and Richfaces. I am having an requirement where I need to change the style of the form field(entire row) if the validation fails. I am using the following code to display field label and text box.
<h:panelGrid columns="2">
<h:outputLabel value="#{uit.firstname}:">
<span class="required"><strong>*</strong> </span>
</h:outputLabel>
<h:inputText value="#{editUserProfileBean.firstName}" type="text"
id="firstname" styleClass="basicFormTextBox" size="30"
required="true" requiredMessage="#{uitkem.valueRequired}"
validatorMessage="#{prod.firstNameValidator}">
<f:validateLength maximum="#{prodConf.MaxLengthForFirstName}"
minimum="#{prodConf.MinLengthForFirstName}" />
<f:validator validatorId="trimSpaces" />
</h:inputText>
</h:panelGrid>
Suppose if the validation fails, I need to hightlight the row(both label and textbox).
I can use the following code to hightlight the textbox if the validation fails. But I want to hightlight the entire row, that is not possible using the following code.
<h:inputText value="#{editUserProfileBean.firstName}" required="true" styleClass="#{not component.valid ? 'newStyleClass' : ''}" />
Can anyone help me on this?
Thanks in advance.
You could just write a tiny JS script with jQuery, or use <rich:jQuery> for that.