JSF Primefaces Validation across dialogs with specific area [duplicate] - validation

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" />

Related

Performing data binding during ajax-request

I have the following markup:
<rich:panel id="selectorPanel">
<h:inputText value="#{myBean.field1}" />
<h:inputText value="#{myBean.field2}" />
<h:inputText value="#{myBean.field3}" />
<!-- and so forth -->
<h:selectOneMenu id="selector" value="#{myBean.selected}">
<a4j:ajax event="change" listener="#{myBean.doUpdateValues()}" render="selectorPanel" />
<f:selectItem itemLabel="#{msgs['bundle.addFilter']}" itemValue="#{null}" value="#{null}"/>
<f:selectItems value="#{myBean.filters}" />
</h:selectOneMenu>
</rich:panel>
The problem: when I change the value of the selectOneMenu the selectorPanel is being rerendered, therefore the values of the inputTexts are being refreshed and set to the myBean's properties value.
But I need to set values entered by user on the web-page to the corresponding bean's properties before rerendering.
Is it possible? How?
Why to do need to execute all? the #form should be enough or even list of inputs ids.
I've found the solution just now and we can actually use execute attribute as follows:
execute="#all"
It works for me.

Validate two components with dynamic id

Here is what I am trying to do:
I have a form with multiple pairs of input fields and a save button.
When the save button is pressed then for each pair of input fields should be validated if they are numbers and if the left value is smaller than the right value.
If not the validation errors will be shown and if it is the case a dialog will pop up to ask for the name under which it should be saved.
Here is what I got so far:
<h:form>
<ui:repeat value="#{myBean.someList}" var="elem">
<h:inputText id="min#{elem.id}" value="#{elem.minimum}" />
<h:inputText id="max#{elem.id}" value="#{elem.maximum}" />
<br />
<h:message for="min#{elem.id}" style="color:red" />
<h:message for="max#{elem.id}" style="color:red" />
</ui:repeat>
<h:commandButton value="save">
<f:ajax execute="#form" render="#form updateValidationFailedFlag"
onevent="
function(ajaxResult){
if(ajaxResult.status=='success' && !globalValidationFailedFlag)
showSaveDialog();
}"
/>
</h:commandButton>
<h:outputScript id="updateValidationFailedFlag">
globalValidationFailedFlag = #{facesContext.validationFailed};
</h:outputScript>
</h:form>
This works but doesn't check if the minimum is smaller then the maximum.
It will validate the input (checks if the input are integer) and shows the save dialog if no validation error occured.
To check if the minimum is smaller then the maximum I tried to follow the tutorial at http://www.mkyong.com/jsf2/multi-components-validator-in-jsf-2-0/
Variant 1 adds a listener after the validation is done and is able to add error messages that are shown in the browser. But that doesn't count as a validation failure and doen't set the facesContext.validationFailed flag.
Variant 2 writes a custom validator for one component and gives the other component as parameter to that validator. That would look something like this:
<f:validator validatorId="myValidator" />
<f:attribute name="maximum" value="#{max#{elem.id}}" />
That is not really valid EL and I don't know how to write it correctly.
What can I do to validate if each of those min-max pairs is valid
You don't need #{elem.id} here. The <ui:repeat> already takes care of that. It would be evaluated to an empty string anyway when JSF needs to set the id attribute.
<ui:repeat value="#{myBean.someList}" var="elem">
<h:inputText id="min" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}" />
<br />
<h:message for="min" style="color:red" />
<h:message for="max" style="color:red" />
</ui:repeat>
As to the validation, just pass the value of the other component along:
<h:inputText id="min" binding="#{min}" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}">
<f:validator validatorId="myValidator" />
<f:attribute name="min" value="#{min.value}" />
</h:inputText>
Note that I moved the validator to the second component. Otherwise it would be still invoked if the second component didn't pass conversion.
If you happen to use JSF utility library OmniFaces, then you could use its <o:validateOrder> instead.
<h:inputText id="min" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}" />
<o:validateOrder components="min max" showMessageFor="min" />
See also:
How to use EL with <ui:repeat var> in id attribute of a JSF component
JSF doesn't support cross-field validation, is there a workaround?

h:inputText is not ajax-rendered on change of h:selectOneMenu

I have this code which is used to select how many rows to display in jsf table:
<!-- Set rows per page -->
<h:outputLabel for="rowsPerPage" value="Rows per page" />
<h:inputText id="rowsPerPage" value="#{AccountsController.rowsPerPage}" size="3" maxlength="3" />
<h:commandButton styleClass="bimage" value="Set" action="#{AccountsController.pageFirst}" >
<f:ajax render="#form" execute="#form"></f:ajax>
</h:commandButton>
<h:message for="rowsPerPage" errorStyle="color: red;" />
I want to edit the code this way: I want to replace the code with h:selectOneManu and option to insert custom value with AJAX support:
<h:selectOneMenu id="setrows" value="#{AccountsController.rowsPerPage}" converter="javax.faces.Integer" maxlength="3">
<f:selectItem itemValue="10" itemLabel="10" />
<f:selectItem itemValue="50" itemLabel="50" />
<f:selectItem itemValue="100" itemLabel="100" />
<f:selectItem itemValue="500" itemLabel="500" />
<f:selectItem itemValue="332" itemLabel="Custom" />
<f:ajax render="customrowperpage" />
</h:selectOneMenu>
<h:inputText id="customrowperpage" value="#{AccountsController.rowsPerPage}" rendered="#{AccountsController.rowsPerPage == '332'}" required="true" />
But for some reason the code is not working. Can you help me to find the problem. Also I want to update AJAX functionality when I select number from the h:selectOneMenu list AJAX call to update the form.
There are 2 problems.
First, as JavaScript runs in the client side, you can't ajax-update a JSF component which isn't rendered to the client side. There's then simply nothing in the HTML DOM tree which JavaScript can select, manipulate and replace. You should instead ajax-update a JSF component which is always rendered to the client side.
<h:panelGroup id="customrowperpage">
<h:inputText value="#{AccountsController.rowsPerPage}" required="true"
rendered="#{AccountsController.rowsPerPage == '332'}" />
</h:panelGroup>
See also Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
Second, an Integer never equals a String. You're in the rendered attribute testing Integer rowsPerPage against String '332'. Remove those singlequotes to make it a fullworthy number.
<h:panelGroup id="customrowperpage">
<h:inputText value="#{AccountsController.rowsPerPage}" required="true"
rendered="#{AccountsController.rowsPerPage == 332}" />
</h:panelGroup>

Temporarily disable JSF validations

A has many required inputs and validations. A couple of command buttons control different inputs.
I can change required attibrute with the value of <f:param>. For instance when a button is clicked,it sets a value.This value changes if an input is required or not. Like this:
<p:commandButton>
<f:param name="button1" value="1"></f:param>
</p:commandButton>
<h:inputText required="#{param['button1'] == 1}"></h:inputText>
This actually works.However i also want to add some valitations like max length.I want to temporarily change this validation too.
I tried to disable valitadion,but i did not work:
<f:validateLength disabled="true" maximum="10"></f:validateLength>
You seem to be using JSF 2.x already. So just use <f:ajax execute> or <p:commandButton process> to specify client IDs of components which are to be executed/processed when the button is pressed. All components which are not included in this will just be ignored and not converted/validated.
E.g.
<h:inputText id="input1" ... required="true" />
<h:inputText id="input2" ... required="true" />
<h:inputText id="input3" ... required="true" />
<h:inputText id="input4" ... required="true" />
<p:commandButton value="Submit inputs 1 and 2" process="input1 input2" ... />
<p:commandButton value="Submit inputs 3 and 4" process="input3 input4" ... />
In case of <p:commandButton> it defaults to #form (i.e. the entire current form).
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

How to let validation depend on the pressed button?

I have created form and I want to show previous existing items on a table while a new one is creating. I'd like to show matching items as form is filling up. But when I try to filter the list without having the form completed, the validation messages appear and the table doesn't get updated.
Don't know if it's possible, but what I want to do something like this:
<h:form id="form">
<h:outputText value="Name: "/>
<p:inputText value="#{itemsBean.name}" id="name" required="true"/>
<br/>
<h:outputText value="Description: "/>
<p:inputText value="#{itemsBean.description}" id="description" required="true"/>
<p:commandButton value="Save" update="form" actionListener="#{itemsBean.save}"/> //validate and save
<p:commandButton value="Filter" update="form" actionListener="#{itemsBean.updateItemsList}"/> //don't validate, and update the table.
<p:dataTable id="list" value="#{itemsBean.itemsList}" var="item">
<p:column>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<h:outputText value="#{item.description}"/>
</p:column>
</p:dataTable>
</h:form>
I'm very new to JSF.
I understand that you want to filter based on the name input field. The <p:commandButton> sends by default an ajax request and has a process attribute wherein you can specify which components you'd like to process during the submit. In your particular case, you should then process only the name input field and the current button (so that its action will be invoked).
<p:commandButton process="#this name" ... />
The process attribute can take a space separated collection of (relative) client IDs of the components, wherein #this refers to the current component. It defaults in case of <p:commandButton> to #form (which covers all input fields of the current form and the pressed button), that's why they were all been validated in your initial attempt. In the above example, all other input fields won't be processed (and thus also not validated).
If you however intend to skip the required validation for all fields whenever the button in question is been pressed, so that you can eventually process multiple fields which doesn't necessarily need to be all filled in, then you need to make the required="true" a conditional instead which checks if the button is been pressed or not. For example, let it evaluate true only when the save button has been pressed:
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:commandButton binding="#{save}" value="Save" ... />
This way it won't be validated as required="true" when a different button is pressed. The trick in the above example is that the name of the pressed button (which is essentially the client ID) is been sent as request parameter and that you could just check its presence in the request parameter map.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
I Have tested this with non-ajax submits:
<p:inputText ... required="#{not empty param.includeInSave1}" />
...
<p:inputText ... required="true" />
...
<p:commandButton value="Save1" ajax="false">
<f:param name="includeInSave1" value="true" />
</p:commandButton>
<p:commandButton value="Save2" ajax="false" />
The first input is required validated only on Save1 button submit.
Additionally to the BalusC answer (very useful and complete) I want to add that when you use a <h:commandButton /> it will validate (required, custom validations) all the fields in the <h:form /> where the command button is located, therefore when you need to use more than one command button you could consider that it is a good practice to use different <h:form /> to different responsibilities to avoid unexpected behavior in submit actions of the command buttons.
It is well explained in a BalusC answer: Multiple h:form in a JSF Page
If your form has validations and you do not update the <h:form /> or you do not show messages, you could get a headache thinking that the <h:commandButton /> is not firing your action, but likely is a validation problem that has not been shown.
Change your filter commandbutton like this to ignore validation:
<p:commandButton value="Filter" update="list" actionListener="#{itemsBean.updateItemsList}" process="#this"/>
EDIT:
The related post on SO, I think this will solve your issue too
JSF 2.0: How to skip JSR-303 bean validation?

Resources