How to skip validation on certain fields in JSF 2 when required - validation

I have two p:dialog. Each one contains some input fields which are marked as required. Only one dialog is shown at a time but when I submit on any of the dialog, JSF also validates the input fields of the dialog which is not shown. What is the best approach to skip the validations in JSF 2 for the dialog which is not shown. One approach could be that I set the required="condation". But dont know what that condition could be and is it goin to work.
Each dialog is initially hidden. Each one has its own button to show. When one is active and I click the save button there is a validation error even when the required field has values. The validation error comes from the inactive dialog panel. May be it give some idea what i am trying to do.
UPDATE
<p:dialog header="Edit Group" widgetVar="dialog_groupEdit" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupEdit" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameEdit" size="26" value="#{groupBean.selectionGroup.gname}" required="true" requiredMessage="Edit Group: Name is required."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.selectionGroup.description}"/>
<div></div>
<p:commandButton value="Save" action="#{groupBean.saveGroupChanges}" oncomplete="#{args.validationFailed ? '':'dialog_groupEdit.hide()'}"
update="panel_groups panel_groupEdit" style="float:right;"/>
<div></div>
<p:message for="input_gnameEdit"/>
</h:panelGrid>
</p:dialog>
<p:dialog header="New Group" widgetVar="dialog_groupCreate" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupCreate" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameCreate" size="26" value="#{groupBean.createGroup.gname}" required="true" requiredMessage="New Group: Name is reqired."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.createGroup.description}"/>
<div></div>
<p:commandButton value="Save" actionListener="#{groupBean.saveGroupCreate}" oncomplete="#{empty groupBean.createGroup.gname ? ' ':'dialog_groupCreate.hide()'}"
update="panel_groupCreate panel_groups" style="float:right;"/>
<div></div>
<p:message for="input_gnameCreate"/>
</h:panelGrid>
</p:dialog>

One approach could be that I set the required="condation".
This is going to be clumsy. Just put each individual form in its own separate <h:form> component, or use the process attribute of the <p:commandButton> to identify the region you'd like to process.
<p:commandButton process="panel_groupEdit" ... />
...
<p:commandButton process="panel_groupCreate" ... />
Having a "God" form is in any way a poor practice.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?

When you are using <p:dialog some of the good practices as advised on the PF forum are -
Never put your <p:dialog inside any other component. Place it somewhere so that it falls right under the <h:body.
Give every <p:dialog it's own form. But, don't place the dialog inside the form, place the form inside the dialog. It's not good to update the dialog itself, only it's content. (I think this should solve your issue also.)
e.g.
<p:dialog widgetVar="dlg" ...
<h:form ...
<h:panelGroup id="dlgContent" ...

Related

o:validateOrder not applied when using PFS in process attribute

In testing the validateOrder validator in OmniFaces 1.8.1, it seems that the validator is not applied to components when used in conjunction with a Primefaces commandButton that partially submits components based on a PrimeFaces Selector (PFS). A sample is below, which is a stripped-down, but representative, test case of my app's usage.
<h:body>
<h:form>
<p:commandButton value="Show" action="#{testBean.save}" oncomplete="PF('testDialogJS').show()"/>
</h:form>
<p:dialog header="Test Dialog" widgetVar="testDialogJS" resizable="false" closeOnEscape="false" closable="false" modal="true" dynamic="true">
<h:form>
<p:tabView>
<p:tab title="Tab 1">
<p:panel header="Tab 1 Panel" styleClass="tab1Panel">
<p:outputLabel value="Test 1"/>
</p:panel>
</p:tab>
<p:tab title="Tab 2">
<p:panel header="Tab 2 Panel" styleClass="tab2Panel">
<h:panelGrid columns="2">
<p:outputLabel for="startDate" value="Start Date: "/>
<h:panelGroup>
<p:calendar id="startDate" value="#{testBean.startDate}" navigator="true" pattern="M/d/yyyy"
required="true" requiredMessage="Start Date is required"/>
<p:message for="startDate"/>
</h:panelGroup>
<p:outputLabel for="endDate" value="End Date: "/>
<h:panelGroup>
<p:calendar id="endDate" value="#{testBean.endDate}" navigator="true" pattern="M/d/yyyy"
required="true" requiredMessage="End Date is required"/>
<p:message for="endDate"/>
<o:validateOrder id="campaignDateRangeValidator" components="startDate endDate" message="Start Date must be before End Date"/>
<p:message for="campaignDateRangeValidator"/>
</h:panelGroup>
</h:panelGrid>
</p:panel>
</p:tab>
</p:tabView>
<p:commandButton value="Save" action="#{testBean.save}"
process="#form" update="#form"
oncomplete="if (!args.validationFailed) { PF('testDialogJS').hide(); }"/>
</h:form>
</p:dialog>
</h:body>
Setting the start date to, say, 10/1/2014, and the end date to 9/30/2014, then clicking the save button, the validator error message is properly displayed. However, if the commandButton's process attribute is set to #(.tab2Panel :input) #this, the validator is never called in code. I breakpointed in ValidateOrder's validateValues method - it's never called. And thus, the action is allowed to proceed.
Looking at the AJAX XHR, javax.faces.partial.execute is set to the component ID of the form in the passing case, while it's set to the explicit list of individual field component IDs to bind in the failing case (without the component ID of the form).
Is this a bug? Unsupported? etc? If unsupported, any suggestions on how to handle this desired usage? Thanks!
The OmniFaces multi-field validators are designed as UI components, because it's among others otherwise not possible to get multi-field validation to work inside e.g. a <h:dataTable>. On contrary to standard JSF validators such as <f:validator>, which are basically taghandlers, the <o:validateOrder> component must therefore also be covered in the process attribute of <p:commandButton> (and equivalently also in execute attribute of <f:ajax>).
Your best bet is to explicitly process the entire tab instead of only the tab's input components. E.g.
<p:tabView id="tabs">
<p:tab id="tab2">
...
</p:tab>
</p:tabView>
<p:commandButton ... process="#this tabs:tab2" />

All dialogs update the backing bean

I have 2 dialogs on a xhtml page:
<p:dialog width="400" id="dialog1" header="Download" widgetVar="dialog1">
<h:outputText value="Field1"/>
<h:inputText value="#{backingBean.field1}"/>
<br/>
<h:outputText value="Field2"/>
<h:inputText value="#{backingBean.field2}"/>
<br/>
<p:commandButton value="Download" ajax="false" onsuccess="PF('diaglog1').hide();">
<p:fileDownload value="#{backingBean.file}"/>
</p:commandButton>
</p:dialog>
<p:dialog width="400" id="dialog2" header="Send" widgetVar="dialog2">
<h:outputText value="Field1"/>
<p:inputText value="#{backingBean.field1}"/>
<br/>
<h:outputText value="Field2"/>
<h:inputText value="#{backingBean.field2}">
<p:ajax update="somePanel"/>
</h:inputText>
<br/>
<h:outputText value="Recipient"/>
<h:panelGroup id="somePanel">
<p:selectOneMenu style="width: 100%;" var="recipient">
<f:selectItems value="#{backingBean.someList}"/>
</p:selectOneMenu>
</h:panelGroup>
<br/>
<p:commandButton value="Send" actionListener="#{backingBean.sendSomething}" onsuccess="PF('dialog2').hide();">
<f:attribute name="item" value="#{recipient}"/>
</p:commandButton>
</p:dialog>
They have different functionality but are on the same page and using the same backing bean. Only one dialog can appear at a time. The problem is when I input some value into the first dialog and press 'Download', it will update the field1 and field2 of the backing bean to the value that I want, but after that the second dialog also updates it to its value, which causes the first one to download the wrong file. If I remove the second dialog, the first will behave correctly.
How do I stop the second dialog from updating the values?
I guess you are keeping both dialogs in one single h:form component.
Then obviously submit in one dialog will submit fields in both dialogs coz, they are in same form.
Don't keep p:dialog inside a h:form, instead use h:form inside
dialog.
You can use multiple h:form s in a page there is no harm in
that, but should not use one h:form in another.
Decide how many forms you can use, based on your design and functionality, In your case you can use 2 h:forms each one inside both dialogs.

Validation errors in dialog not updating after failed submit in JSF

So I click a button which opens a dialog. Inside this dialog I want to fill out information in a form and submit and save it. Some of the inputTexts need to be required in order to submit. So I use the required="true" attribute. It stops the submission, but it does not update the field with a red outline of everything. Now, if I hit cancel and open up the dialog again it will show the fields that failed validation with a red outline!
I thought I could solve this by manually updating the dialog whenever I try to submit the form. This just causes the dialog to close though instead of staying open and refreshing the dialog to show the validation failures.
This is the dialog, when I hit the save button is when I submit the form
<h:form>
<p:dialog header="#{headerValue}" widgetVar="#{uniqueId}_editDialog"
modal="false" showEffect="fade" styleClass="dialogGrid"
dynamic="true" draggable="true" resizable="false">
<p:outputPanel style="text-align:center;" layout="block">
<p:messages autoUpdate="true"/>
<ui:insert name="editContent">
Edit Content Here. Use 'selectedModel.whatever'
</ui:insert>
<p:panelGrid columns="3" styleClass="buttonGrid">
<ui:insert name="saveButton">
<p:commandButton iconPos="left" value="#{msg.save}"
rendered="#{'VIEW' != selectedModel.viewState}"
process="#widgetVar(#{uniqueId}_editDialog)"
action="#{adapterInjector.add(modelList, selectedModel)}"
update="#widgetVar(#{uniqueId}_itemsDataList) #widgetVar(#{uniqueId}_addButton) #widgetVar(#{uniqueId}_editDialog)"
oncomplete="if(!args.validationFailed) PF('#{uniqueId}_editDialog').hide()"
partialSubmit="true" validateClient="true">
</p:commandButton>
</ui:insert>
<p:commandButton iconPos="right" value="#{msg.cancel}"
process="#this" oncomplete="PF('#{uniqueId}_editDialog').hide()"
resetValues="true" partialSubmit="true">
</p:commandButton>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
This is an inserted component which has the required attribute
<p:selectOneMenu id="licenseCert"
value="#{selectedModel.selectedLicenseCert}" filter="true"
required="true">
<f:selectItem itemLabel="#{msg.selectOne}" itemValue=""
noSelectionOption="true" />
<f:selectItems value="#{licCert.allLicenseCertMap.entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
</p:column>
Turns out this fixed the problem.
For best practice you should:
move the <h:form> inside the dialog
process the moved <h:form> in the save button.

Ajax not working with primefaces

In my JSF page I have form when I click submit button in the same page I need to show an static content. But When I click <p:commandbutton> nothing appears in the page. When I put ajax="false" then only action taken place but the Static content display in new page.
In my Backing bean I have used Session scoped. I am using JSF 2.0 and Primefaces 3.2.
My JSF Page.
<h:form>
<h:panelGroup rendered="#{not license.showForm}">
<p:panel header="License Key Request" >
<h:panelGrid columns="2" >
..
<h:outputText value="Bla bla"/>
..
<h:outputText value="Bla Bla" />
</h:panelGrid>
<TABLE>
..
<h:outputLabel for="name" value="Requestor Name : *" />
..
<p:inputText id="name" value="#{license.name}" required="true" requiredMessage="Name is required."/>
..
<h:outputLabel for="company" value="Company : * " />
..
<p:inputText id="company" value="#{license.company}" required="true" requiredMessage="Company is required."/>
..
</table>
<p:commandButton value="Form" id="btnAdd" process="#form"
action="#{license.add}" />
..
</table>
</p:panel>
</h:panelGroup>
<h:panelGroup rendered="#{license.showForm}" >
<h:outputText value="Bla Bla"/>
</h:panelGroup>
</h:form>
Your source code is somewhat confusing (e.g. you have two closing table tags). But I assume that you want to show the panelGroup at the bottom if the button is clicked.
The easiest way would be to add an update ="#form" to your commandButton:
<p:commandButton value="Form" id="btnAdd"
process="#form" update="#form"
action="#{license.add}" />
You don't need to update the whole form but only the specific component. Then you need to give the panelGroup an id attribute and use this attribute instead of #form. However, since it is not clear for me how your naming containers are organized, it could be puzzling to find the correct relative id.

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