Show message only when there are no messages for other components - forms

I have 3 messages displayed when validating the form, kind of this :
<p:message id="msgCity1" for="city1" styleClass="required" display="text" />
<p:message id="msgCity2" for="city2" styleClass="required" display="text" />
<p:message id="msgCountry" for="msgCountry" styleClass="required" display="text" />
the first(msgCity1) and second(msgCity2) messages are validated on event (keyup)
the last one is validate on server side, I would like to show the last message (msgCountry), if the validation is ok for the first 2 messages, I mean if the message are empty,
For that I would like to use rendered on the last message but I do not how I can get the value of the first 2 message in xhtml

Rather hook on UIInput#isValid() directly than on the presence of a message for the input.
E.g.
<h:inputText id="city1" binding="#{city1}" ... />
<h:inputText id="city2" binding="#{city2}" ... />
...
<p:message for="msgCountry" ... rendered="#{city1.valid and city2.valid}" />

Related

Primefaces Form with 2 buttons dont update

I have a form that has an inputtext where the operator enters the clientid and click on "search", when the search is done the other fields in the form are populated correctly.
Then I have the button "new record" that calls a procedure that creates another object (not a customer) and needs to persist it, when the other object is created in the bean it takes every field from the form except a timestamp.
When the object is persisted only the timestamp is in the DB, all the form values are set to null.
<h:form id="myForm">
<h:outputText value="Customer number" />
<h:inputText id="cIdentidad" value="#{custBean.custID}" />
<p:commandButton process="#all" update="#all" action="#{custBean.populateFields(custBean.custID)}" value="Search" />
<p:growl />
<h:panelGrid id="newCust" columns="2" style="margin-top: 15px">
<h:outputText value="Name" />
<h:inputText id="name" value="#{custBean.name}" disabled="true"/>
<h:outputText value="more fields" />
<h:inputText id="nroAgenda" value="#{custBean.morefields}" disabled="true"/>
</h:panelGrid>
<p:commandButton process="#all" update="#all" action="#{custBean.newRecord()}" value="New record" />
</h:form>
The h:inputText's are disabled, so the value will not be submitted to the server. Maybe you're looking for readonly="true".
Also I would'nt use #all everywhere but rather #form. update="#all" has a special meaning.
Also see this answer.

<h:form action="#{bean.method()}"> gets called twice

I am writing a Java EE application for changing password. For taking old and new password inputs I am using a jsf form.
<h:form method="post" action="#{changePass.updatePassword()}" >
<h:inputText id="username" value = "#{changePass.username}" readonly="true" required="true"/>
<h:inputSecret id="oldPassword" value = "#{changePass.oldPassword}" required="true" />
<h:inputSecret id="newPassword" value = "#{changePass.newPassword}" required="true" />
<h:inputSecret id="confirmPassword" value = "#{changePass.confirmPassword}" required="true" />
<button id="update" type="submit"></button>
</h:form>
My intention is to call updatePassword() function in changePass bean class when user clicks on the button. But this fuction gets called twice in this form.
when the form loads
When the user clocks on the button
How can I avoid this calling during the form load?
Your xhtml should look like this:
<h:form>
<h:inputSecret id="newPassword" value = "#{changePass.newPassword}" required="true" />
<h:commandButton value="submit" action="#{changePass.updatePassword}" />
</h:form>
If that still doesn't work then there is smtg wrong with your bean. Also you might want to follow some tutorials. I'm not entirely sure the syntax you used is wrong but it's the first time I've seen it though.

Ignore custom validation, but not the required="true" depending on button pressed

I am using JSF and I want to validate a form.
In the form is a text field that is validated by required="true" and a validator method.
<h:inputText
required="true" requiredMessage="Please enter a topic"
validator="#{eventController.validateTopic}" />
To submit the form I have two buttons. When clicking on the first, it should be only validate if the field is empty. By the second one the custom validation should be additionally invoked.
Is this possible?
First turn that validation method into a true Validator implementation.
#FacesValidator("topicValidator")
public TopicValidator implements Validator {}
Then you can use it in a <f:validator> which supports disabled attribute.
<h:inputText ...>
<f:validator validatorId="topicValidator" disabled="..." />
</h:inputText>
To let it check if a certain button is pressed, just check the presence of its client ID in the request parameter map.
<h:inputText ...>
<f:validator validatorId="topicValidator" disabled="#{empty param[secondButton.clientId]}" />
</h:inputText>
...
<h:commandButton binding="#{secondButton}" ... />
Note: do absolutely not bind it to a bean property! The above code is as-is. You should only guarantee that the EL variable #{secondButton} is unique in the current view and not shared by another component or even a managed bean.
See also:
How to let validation depend on the pressed button?
How does the 'binding' attribute work in JSF? When and how should it be used?

Validate only specific parts of the form instead of whole form

I have a whole form with a lot of components including a p:tab
When I click on p:commandButton id=c1 to submit the whole form content:
I need to validate the whole form required messages but I do need to ignore the p:tab required messages fields.
If I click on p:commandButton id=c2 inside the p:tab, I need to validate only the required messages fields inside the p:tab.
What is the best solution for this ? Thanks in advance.
You seem to be using the "God Form" anti-pattern. Everything is thrown together in a single <h:form>. This is a poor design/practice. Most sensible way would be to put the fields and buttons in separate forms so that only the related fields and buttons are in its own form so that the form submit doesn't unnecessarily submit/process/convert/validate irrelvant data in other forms.
See also:
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
If that's not possible due to some (strange?) design restrictions, then there are at least 2 other ways:
If you're using ajax, then you can make use of the process attribute. It defaults to #form which would process the entire form. It accepts a space separated string of (relative) client IDs of input field which you'd like to process during submit.
<p:inputText id="field1" ... required="true" />
<p:inputText id="field2" ... required="true" />
...
<p:inputText id="field3" ... required="true" />
<p:inputText id="field4" ... required="true" />
...
<p:commandButton id="c1" ... process="field1 field2" />
...
<p:commandButton id="c2" ... process="field3 field4" />
See also: Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
If you're not using ajax, or desire a non-ajax fallback, then just check in the required attribute which button has been pressed. This is easy by checking the presence of the button's client ID in the request parameter map.
<p:inputText id="field1" ... required="#{not empty param[c1.clientId]}" />
<p:inputText id="field2" ... required="#{not empty param[c1.clientId]}" />
...
<p:inputText id="field3" ... required="#{not empty param[c2.clientId]}" />
<p:inputText id="field4" ... required="#{not empty param[c2.clientId]}" />
...
<p:commandButton id="c1" binding="#{c1}" ... />
...
<p:commandButton id="c2" binding="#{c2}" ... />
(note: no additional bean properties necessary for c1 or c2! the code is as-is)
See also How to let validation depend on the pressed button?
You can refactor this somewhat with a more self-documenting variable name:
<c:set var="c1ButtonPressed" value="#{not empty param[c1.clientId]}" />
<c:set var="c2ButtonPressed" value="#{not empty param[c2.clientId]}" />
...
<p:inputText id="field1" ... required="#{c1ButtonPressed}" />
<p:inputText id="field2" ... required="#{c1ButtonPressed}" />
...
<p:inputText id="field3" ... required="#{c2ButtonPressed}" />
<p:inputText id="field4" ... required="#{c2ButtonPressed}" />
...
<p:commandButton id="c1" binding="#{c1}" ... />
...
<p:commandButton id="c2" binding="#{c2}" ... />
FYI you can also process the id of a panel containing the controls you want to validate - example :
<p:outputPanel id="thisPanel">
<p:inputText id="field1" ... required="#{not empty param[c1.clientId]}" />
<p:inputText id="field2" ... required="#{not empty param[c1.clientId]}" />
<p:commandButton id="c2" ... process="thisPanel" />

Why the form id prefix in the h:message output?

I'm currently trying simple validation using required="true"
<h:form>
<h:messages globalOnly="true"/>
<h:panelGrid>
<h:panelGrid columns="3">
<f:facet name="header">
Login Application Sample
</f:facet>
<h:outputLabel for="UserId" value="User Id" />
<h:inputText id="UserId" value="#{userBean.userId}" required="true" />
<h:message for="UserId"/>
<h:outputLabel for="Password" value="Password" />
<h:inputSecret id="Password" value="#{userBean.password}" required="true" />
<h:message for="Password" />
<f:facet name="footer">
<h:commandButton value="Login" action="#{userBean.login}"/>
<h:commandButton type="reset" value="Reset"/>
</f:facet>
</h:panelGrid>
</h:panelGrid>
</h:form>
Leaving the fields blank, and then clickin on the login button, these error messages will display on the right side of each field :
j_idt7:UserId: Validation Error: Value is required.
j_idt7:Password: Validation Error: Value is required.
This is what I expected, but I don't want to display the form id prefix of 'j_idt7:'. I read book examples, they don't output the form id prefix. What I want is :
UserId: Validation Error: Value is required.
Password: Validation Error: Value is required.
What should I do to skip displaying the form id prefix in the component specific messages ?
I'm currently testing JSF 2 in glassfish v3.
The message label defaults to component's client ID, exactly the one as you can see in generated HTML output via rightclick, View Source. That j_id7 is in this particular case the client ID of the parent <form> element. If you give the JSF component a fixed ID like <h:form id="login"> then the labels will become login:UserId and login:Password respectively.
You can however use the input component's label attribute to override it altogether so that the message label will be shown exactly as you intented.
<h:inputText ... label="User ID" />
<h:inputSecret ... label="Password" />
If the input component's label attribute is present, then it will be used instead of the client ID. Using prependId="false" as suggested by other answers has disadvantages. Don't do that.
A completely different alternative is to use requiredMessage (or converterMessage or validatorMessage) attribute for this, but this doesn't allow parameterizing messages and thus you'd have to hardcode the labels and such.
<h:inputText ... label="User ID is required." />
<h:inputSecret ... label="Password is required." />
See also:
Change the default message "Validation Error: Value is required" to just "Value is required"
Getting the component id on the error validation message
How to parameterize requiredMessage attribute in composite component?
Noted should be that it's indeed awkward to have labels duplicated like this:
<h:outputLabel for="userId" value="User ID" ... />
<h:inputText id="userId" ... label="User ID" />
<h:outputLabel for="password" value="Password" ... />
<h:inputSecret id="password" ... label="Password" />
If you happen to use JSF utility library OmniFaces, then you can use <o:outputLabel> to let JSF transparently set the label attribute of the associated component:
<o:outputLabel for="userId" value="User ID" ... />
<h:inputText id="userId" ... />
<o:outputLabel for="password" value="Password" ... />
<h:inputSecret id="password" ... />
If you use MyFaces and the bean validation framework (JSR303) try to define a MessageBundle with a key javax.faces.validator.BeanValidator.MESSAGE
faces-config.xml
<application>
<message-bundle>ApplicationMessages</message-bundle>
</application>
ApplicationMessages.properties
#javax.faces.validator.BeanValidator.MESSAGE={1}: {0}
javax.faces.validator.BeanValidator.MESSAGE={0}
Details
You need to override these messages from JSF.
You can have a messages.properties file in your classpath
Messages.properties
javax.faces.component.UIInput.REQUIRED=Field must be entered.
Faces-config.xml
<application>
<message-bundle>Messages</message-bundle>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
</application>
Have a look at this Article
If you care to see the HTML source from your browser, you will find out that the id of your input field is <form-id>+":"+<input-field-id>, in your case, j_idt7:UserId:. Try to give your <h:form> some meaningful id in order to make some sense out of it. You can read about JSF IDs here. In case you don't like it, you can turn it off by modifying your form tag to something like this,
<h:form prependId = false> // its true by default.
But that might turn out to be problematic, as pointed out by BalusC here.
Furthermore, it seems like you have never configured any validation messages yourself. Which in turn ends up with this message. Hence, a message.properties file is needed to have a control over message and show something more appropriate. Even then the field name should not be the part of the message, to make those validation message generic to avoid repetition. See BalusC's answer regarding the use of label attribute inside the <h:inputText>.
Where you are writing required = true, there you can define requiredMessage = "My Message" for any input type.
e.g.
<h:inputText autocomplete="false" id = "CellNumber" label="Cell Number" required="true" requiredMessage="Cell Number Required" maxlength="10" value="#{userManagedBean.cellNumber}" >