JSF Validation Error from Component that is not Rendered - validation

I have a form that has a field that needs to be rendered as a read-only value when in edit mode and as a drop-down select list when in create mode.
The read-only field (used in edit mode) is rendered as plain text using <h:outputText>. In create mode, the field is rendered <h:selectOneListbox> that has a required attribute of "true".
It seems to work as I expect most of the time, but occasionally I get a validation error when in edit mode (the select list box is not rendered) .
Here is the code snippet that has both fields defined with their rendered attributes set using the same boolean value (just one field negates the boolean to toggle).
<h:outputLabel id="lblBusinessArea" value="Business Area:" />
<h:panelGroup id="baGroup">
<h:selectOneListbox id="businessAreaList" size="1"
rendered="#{shiftDetailsController.canEditBusinessArea}"
converter="businessAreaConverter"
value="#{shiftDetailsController.selectedBusinessArea}"
label="Business Area"
required="true">
<f:selectItems id="businessAreaListItems" value="#{shiftDetailsController.businessAreas}" />
<a4j:support id="businessAreaA4j" event="onchange"
ajaxSingle="true" reRender="deploymentGroupList, positionPayGroupList, sapPremCodeList" />
</h:selectOneListbox>
<h:outputText id="businessAreaRO"
rendered="#{!shiftDetailsController.canEditBusinessArea}"
value="#{shiftDetailsController.selectedBusinessArea.busAreaDesc}" />
</h:panelGroup>
Below is a screen clipping showing the field (in edit mode) rendered as read only. The "save" button was clicked and I get a validation error message that the field is required.
The value should be there in the backing bean because the value displayed is from the same object (shiftDetailsController.selectedBusinessArea). The output text uses the description field on the business area ojbect and the select field uses the whole object where the SelectItem has the description in the label.
Any idea how this could be occurring? I could set the required attribute using the same boolean value that determines the rendered state...so that it is only required when it is rendered...but since this problem is intermittent...I don't know that will really help.
I also verified that no other components on the page inadvertently have a label value of "Business Area" (which is being used in the validation message) to mislead me in which component truly has a null value; this is the only one that has the label of "Business Area".

I figured out what was happening with this issue.
Prior to submitting the form and receiving the validation error. I was making a change that caused the flag controlling the two components' visibility to be reversed.
rendered="#{shiftDetailsController.canEditBusinessArea}"
In other words, what I was doing on the form was causing the canEditBusinessArea to change values. But, I was not re-rendering the panel group ("baGroup") to cause the UI to reflect the update.
Thus, when my form was submitted the component during the validation phase was seen as being required...triggering the validation to happen. As soon as I added "baGroup" to the reRender of the action that was flipping the edit business area flag, the UI began reflecting the update and the submitted form had the value.

Related

How to make a form field conditionally required in JSF?

Suppose I have an h:form with three fields and two submit buttons. The submit buttons are, say, Display Report and Generate Data. For the simplicity, I would prefer to have only one and not multiple forms. When Display Report, the values from the three fields are required as criteria for the report presentation. So I marked them as required="true" but that disables the execution of Generate Data, which does not need those three fields.
Is there a way to make JSF form fields conditionally required without much custom coding, something like requiredIf=#{condition}?
If Generate Data action does not require any conversion or validation of form data then set the attribute immediate to true for this button:
<h:commandButton action="#{someBean.generateData}" value="Generate Data" immediate="true"/>
This way action generateData is invoked before any conversion or validation takes place and form data is not validated at all.
If Generate data needs data from the form then you can use trick described by BalusC here: JSF 2.0 validation in actionListener or action method
In short, as #Jean-François suggested you can use EL expressions as value of required attribute. The EL expression should evaluate to true only when user pressed Display Report button. This could be done using the following expression: #{not empty param['<fullIdOfTheDisplayReportButton>']}. This expression checks whether id of the button belongs to parameters, which means that given button was used to submit the form.
Full example:
<h:form id="formId">
<p>
Required only for Display Report: <h:inputText id="reqForDR" required="#{not empty param['formId:displayReportButton']}" />
</p>
<p>
Required for Display Report and Generate Data: <h:inputText id="reqForDRGD" required="true"/>
</p>
<h:commandButton id="displayReportButton" action="#{someBean.displayReport}" value="Display Report"/>
<h:commandButton id="generateDataButton" action="#{someBean.generateData}" value="Generate Data"/>
</h:form>

How to reRender an inputText generated dynamically by a dataTable using Ajax

I'm using here in my project JSF 1.2 and the Tag <a4j:support> .
Well, i'm using here a <h:dataTable /> to print on the screen a list of financial expenses, where it's possible for the user to insert new expenses or edit the existed expenses at anytime, the value of these expenses fields (amount, balance, value) are being shown in inputTexts components.
As i'm using a <h:dataTable /> the inputTexts of it are generated automatically, so it creates dynamical inputTexts with dynamical ids. I took a look at the html source code of the page and the pattern JSF uses to generate the ids in a dynamically way is this:
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
And in the xhtml page the code i used with the dataTable is this:
<h:inputText id="inputTextValue" value="#{item.value}" label="Value" styleClass="field" size="9" readonly="true" dir="RTL" style="font-size:12px;width:170px">
My business rule works like that: When the user types something in the inputTextBalance it calls the event onBlur where it automatically inserts an other value in the field "value", but to update this inputTextValue i need to do a reRender in my panel (panelDataTable), so it reRender the whole dataTable (dataTable is inside the Panel).
<h:inputText id="inputTextBalance" value="#{item.balance}" dir="RTL">
<f:convertNumber currencyCode="BRL" type="currency" />
<a4j:support event="onblur" reRender="panelDataTable" ajaxSingle="true" action="#{expenses.update}"/>
</h:inputText>
Now comes the trouble, what i need to do is to reRender only the inputTextValue instead of the panel, but these fields are generated dynamically and i can't get there ids. Like i said before, this is the pattern that JSF uses to generate the id of the fields
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
But when i use any of these ids in reRender attribute, the Ajax's log returns me this message:
18:23:57,208 WARN [AjaxContext] Target component for id formTemplate:tableForm:0:inputTextValue not found
I tried this but i got the same error message: reRender="#{rich:clientId('inputTextValue')}"
The weirdest thing here is that it shows me this message of the input not found, but in the html source code the id of he inputText is the same that i've puted to reRender.
Does anybody here have already delt with this problem? Any suggestions to me?
Thank you!
you should bind the h:dataTable to a variable in your bean, in order to reach the current row index.
<h:dataTable binding="#{myManagedBean.dataTable}" ...>
then you can change a4j:support like this:
<a4j:support reRender="formTemplate:tableForm:#{myManagedBean.dataTable.rowIndex}:inputTextValue" ... />

How to use a single <p:messages> for a specific form without duplicating p:growl

I'm using PrimeFaces 5.0 and have a problem with the basic validation messages.
I've many <p:inputText> fields that are all required, how can I link a single <p:messages> to all fields?
If I use the for attribute I can link it just to a single text field.
If I don't use the for attribute the <p:messages> tag catches also messages that are not for him (it duplicates the messages sent to the <p:growl> tag for example).
Just tell the <p:messages> to not redisplay (duplicate, as you say) the already displayed messages. Provided that the <p:growl> in question is being placed in the view before the <p:messages>, then it's a matter of setting its redisplay attribute to false.
<p:growl ... />
...
<p:messages ... redisplay="false" />

setting process for command button inside a dialogue gives blank value

Setting process="#this" inside a <p:dialog> will hit the method in managedBean but the submitted values are empty. Setting process="#form" does not hit a method. Setting process="#all" gives null values. Setting a nested form, introducing a form in a dialogue is not advisable. What do I have to specify in the process attribute?
<p:commandButton id="serachInsideDialogue" value="#{msg.AddSystem_searchLabel}" action="#{testBean.edit}" update="growl" process="#this">
<f:setPropertyActionListener target="#{testBean.searchUserId}" value="#{testBean1.searchId}" />
</p:commandButton>
You can try with some functions like that
function null() { document.getElementById("serachInsideDialogue").style.display= ""; }
and then to customize them as you want for every event.
And them to call them in your process when you want like events.
Introducing a form in a dialogue is not advisable
You have been misinformed.
The dialog must not be placed inside any form. Instead, it must be placed outside any form and in turn have its own form. You obviously don't want to process all other inputs inside the same form outside the dialog when intending to submit the inputs in the dialog.
Once you fix that, you can just use process="#form" which is already the default value and can thus safely be omitted altogether.

Refresh JSF before validation

I am using JSF validation to simply check that the length of a field is 15, if not an error message is shown. My issue with this approach is
that user enters a number which is the correct length and clicks a button and some information is displayed about it. The second time when the user enters a number whose length is <15 then the validation error is shown BUT the information about the previous number remains on the screen.
My trouble is I am not sure how to do a refresh of the page. I do the validation like this:
<h:inputText id="imei" value="#{imeiValidationHandler.imei}" required="true">
<f:validateLength minimum="15" maximum="15"/>
</h:inputText>
Any ideas much appreciated.
On your information section have a attribute that suppresses the display if the length of the imei is less than ideal. eg:
<h:outputText value="#{imeiInformation.value}" rendered="#{sometest}" />
You may also want to look into a4j and rich faces for using AJAX to render your page as things change on the client.

Resources