How to make a form field conditionally required in JSF? - validation

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>

Related

JSF Submit Form to CommandButton using Ajax

https://www.primefaces.org/showcase/ui/ajax/event.xhtml
I want do that same what in showcase but without refreshing page. Like: setting value in inputtext and click on button to view result, but if i have <p:ajax event="blur" />or <p:ajax/> then i must click two times on the button
<p:inputText id="data" value="#{buttonView.data}">
<p:ajax/>
</p:inputText>
<p:commandButton value="Ajax Submit" id="ajax" actionListener="#{buttonView.buttonAction}" />
Maybe something like use outpupanel and update that panel in commandbutton?
If you are to use the <p:commandButton /> then the form will be submitted. In this case use update attribute of <p:commandButton /> to update the target component.
If you want to update another component as soon as you type then use <p:ajax event="keyup" update="your_target_component_id" /> to update your target component. (YOur event can be keyup, keypress, change, blur, etc.)
I don't understand why are you mixing the concept of using p:ajax with the functionality of the p:commandButton.
Basically, usage of p:ajax is intended to partially process the
field(s) value and update the component(s) of the form even without
submitting it.
Example:
You have Countries and States drop-downs (pre-populated) on a screen (let's say registration) with some other fields, but if user changes the country, you need to refill the States drop-down and update on the screen asynchronously. There you need to use the p:ajax.
On the other hand, p:commandButton is intended to submit the form
(not to update the components initially). However, it also supports
the updating of the components using update attribute.
Example:
Now, reconsider the above example with similar drop-downs (but disabled with fixed values). Now you know that your screen has nothing to be updated and you just have to tackle with validation (if any) and submit the form (update if required).
As far as you are concerned with using the p:ajax on the p:inputText for some asynchronously updates on the screen and p:commandButton to finally submit the form, that totally depends on your requriement.
Instead p:ajax try f:ajax. You can use < f:ajax event="change" render="#this"/>
once the value gets change, same will reflect in backing bean.

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

What does ajax do to JSF inputtext?

I have an input textbox that accept a name, process the name in reverse order, and then output it to another textbox. Whenever I input the value and click anywhere on the page (means lost focus from textbox), the output textbox will get update automatically.
When I open up the source code I found something like code below, may I know what does the ajax thing do to the inputtext component?
<h:inputText id="name" value="#{helloBean.name}">
<f:ajax render="printMyName"/>
</h:inputText>
<h:outputText id="printMyName" value="#{helloBean.reverseName}"/>
Taken from Learning JSF2: Ajax in JSF – using f:ajax tag
Sending an Ajax request
JSF comes with one tag to send an Ajax request, the tag is called
f:ajax. This tag is actually a client side behavior. Being a behavior
implies it’s never just used by itself on a page, it is always added
as a child tag (behavior) to another UI component (or can even wrap
several components). Let’s use a small echo application to demonstrate
usage of this tag.
<h:form>
<h:panelGrid>
<h:inputText value="#{bean.text}" >
<f:ajax event="keyup" render="text"/>
</h:inputText>
<h:outputText id="text" value="#{bean.text}" />
</h:panelGrid>
</h:form>
Code snippet above takes care of firing an Ajax request based on onkeyup event. Notice the actual event name is keyup. This takes care of firing an Ajax request. Next we need to figure out how to do partial view rendering.
Attribute Description event:
String on which event Ajax request will be
fired. If not specified, a default behavior based on parent component
will be applied. The default event is action for ActionSource (ie:
button) components and valueChange for EditableValueHolder components
(ie: input). action and valueChange are actual String values that can
be applied applied event attribute.

JSF Validation Error from Component that is not Rendered

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.

Avoid required=true constraint of an input field when changing selection in dropdown

I have a dropdown and a text field next to it. Based on value selected in dropdown I am changing the type of text field, like change it to date, integer, text. Those text fields have required attribute set to true.
So when I select a different value in dropdown, I can change the type of text field but I also get a required error message on the text field. How can I avoid this?
I am using JSF 1.2.
<h:selectOneMenu id="SelectField"
value="#{logSearchBean.searchType}"
onchange="this.form.submit();"
valueChangeListener="#{logSearchBean.searchValueType}" >
<f:selectItems value="#{logSearchBean.columnDesc}" />
</h:selectOneMenu>
<h:inputText id="SearchText"
value="#{logSearchBean.searchValue}"
required="true"
requiredMessage="Please provide value to Search for"
rendered="#{logSearchBean.searchValueEditor eq 'SearchText'}"/>
<t:inputDate id="SearchDate"
value="#{logSearchBean.searchValueDate}"
popupCalendar="true"
required="true"
requiredMessage="Please provide value to Search for"
rendered="#{logSearchBean.searchValueEditor eq 'SearchDate'}"/>
You need to do two things:
Add immediate="true" to the dropdown.
<h:selectOneMenu immediate="true">
This will cause the valueChangeListener method being invoked during apply request values phase instead of the validations phase. Thus, it will be invoked one phase earlier than usual and all other input fields without immediate="true" aren't processed yet at that point.
In the valueChangeListener method associated with the dropdown, call FacesContext#renderResponse().
FacesContext.getCurrentInstance().renderResponse();
This will instruct JSF to bypass all remaining phases until the render response phase. Thus, the other input fields without immediate="true" won't be processed anymore.

Resources