form within form: skip validation of parent form - jsf

<h:form prependId="false" id="parentForm">
...
<h:form prependId="false" id="commentForm">
...
add comment
</h:form>
save
</h:form>
Doesn't work...
Without the inner form the parent's elements get validated when I just want to add a comment.
"add comment" should just validate the comment and when "save" is clicked the parent should be validated.

Nesting forms is illegal in HTML, so also in JSF since all it does is just generating HTML. You need to put them next to each other.
If you have multiple buttons in the same form of which you'd like to skip certain validation on certain button press, then add immediate="true" to the button in question. This way all input fields which do not have immediate="true" will be skipped.
See also:
What is the immediate attribute used for?
Update: OK, you want two physically separate forms inside a single form. If splitting the "God Form" in multiple forms with each its own responsibility is not an option, then there are several ways to go around this:
If you don't use Ajax and you just have a required="true" on an input element which you actually want to make non-required when you press a certain button, then do:
<h:form>
...
<h:commandButton value="Submit form but but do not validate comment" />
...
<h:inputTextarea id="comment" required="#{not empty param[foo.clientId]}" immediate="true" />
<h:commandButton binding="#{foo}" value="Submit and validate comment" immediate="true" />
</h:form>
If you actually use Ajax, then just specify the execute region in execute attribute.
<h:form>
<h:panelGroup id="other">
....
<h:commandButton value="Submit form but but do not validate comment">
<f:ajax execute="other" render="other" />
</h:commandButton>
</h:panelGroup>
<h:panelGroup id="comments">
<h:inputTextarea required="#{not empty param[foo.clientId]}" />
<h:commandButton value="Submit and validate comment by ajax">
<f:ajax execute="comments" render="comments" />
</h:commandButton>
</h:panelGroup>
</h:form>

Related

SelectOneMenu required when a certain button is pressed

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?

Primefaces dialog doesn't update when is open [duplicate]

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?

Two h:forms inside one h:form

I have two primefaces dialog that are inside in one h:form and i want to submit some required values from one dialog without submit required values from the other one:
<h:form>
<p:dialog modal="true" widgetVar="A">
<h:inputText value="#{bean.value}" required="true" />
<p:commandButton value="A" action="#{bean.someAction}" />
</p:dialog>
<p:dialog modal="true" widgetVar="B" >
<h:inputText value="#{bean.otherValue}" required="true" />
<p:commandButton value="B" action="#{bean.someOtherAction}" />
</p:dialog>
</h:form>
If i press commandButton A the validation of required value inside dialog B dont let me submit values from dialog A.
How can i do that?
The best and the logical solution is to split dialogs into separate forms. Moreover, the best practice is to put the form inside the dialog, and not vice versa.
Another solution is to explicitly tell JSF/PrimeFaces what to update and to process during an ajax request by specifying the corresponding attribute of your command button, or nesting an ajax tag inside the button.

How to collapse or expand all RichFaces collapsiblePanel elements on the page?

I'm using RichFaces with JSF to develop a simple app. One page of this app contains several collapsiblePanel elements. Some of the collapsiblePanel elements are nested, but never more than a second layer.
I would like to provide links or buttons on the page to expand all and collapse all collapsiblePanel elements on the page. How can I do that?
The elements currently use the switchType="client" attribute to let the client handle the expanding and collapsing. I suspect that using a type of ajax instead may help, but I'm not sure nor do I know how I would take advantage of it.
Update: My question may be easier to understand if I include an example of what I'm trying to do:
<h:form>
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(true)}"
render="reportPanel" value="Expand all" />
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(false)}"
render="reportPanel" value="Collapse all" />
<h:panelGrid id="reportPanel">
<ui:repeat var="account" value="#{bean.results.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<ui:repeat var="chargeGroup" value="#{account.value.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<h:outputText value="content: #{chargeGroup.value}" />
</rich:collapsiblePanel>
</ui:repeat>
</rich:collapsiblePanel>
</ui:repeat>
</h:panelGrid>
</h:form>
The <rich:collapsiblePanel> has the expanded attribute, you can bind it to bean property and control the expansion from there. Something like this
<rich:collapsiblePanel id="panel1" expanded="#{bean.expanded}" …>
<a4j:commandButton actionListener="#{bean.togglePanels()}"
… render="panel1, panel2, …"/>
The switchType controls where the content is pulled from, not how you expand/collapse the panel.
I had the same problem when click individual panels and then expand/collapse all. This work for me (richfaces 4.2.3):
<h:commandButton immediate="true" action="#{controllerBean.toggleMin}" value="collapse all" >
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
<h:commandButton immediate="true" action="#{controllerBean.toggleMax}" value="expand all">
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
...
<rich:collapsiblePanel id="panel1" immediate="true" expanded="#{modelBean.expanded}" header="Title text" switchType="client">
...
</rich:collapsiblePanel>
...

Single JSF form on a page approach vs several forms?

Does it makes sense to merge these several hidden forms on a single page into just one single big form?
To submit a particular set of parameters belonging to a particular form process attribute could be used to submit all elements required to be processed.
What are the pro/cons of this single form approach over using several forms?
<span class="hiddenForms">
<h:form>
<h:inputHidden id="selctdChnlType_in" value="#{channelCntlr.type}"/>
<h:inputHidden id="selctdChnlId_in" value="#{channelCntlr.channelId}"/>
<p:remoteCommand name="updateChnlDataPanel" process="#form" actionListener="#{channelCntlr.init()}" update=":channelHeader, :channelDataPanel, :channelSideColumn"/>
</h:form>
<h:form>
<h:inputHidden id="selctdLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<p:remoteCommand name="updateLOBPanel" process="selctdLOBId_in, #this" actionListener="#{lobCntlr.retrieveCurrentLOB()}" update=":lobFullContentPanel" />
</h:form>
<h:form id="lobAction_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
</h:form>
<h:form id="comment_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
<h:form id="recosForm">
<h:inputText id="startFromRecos_in" value="#{recmdnsCntlr.startFromIndex}"/>
<p:remoteCommand name="fetchAllRecos" actionListener="#{recmdnsCntlr.retrieveAllRecmmndns()}" process="startFromRecos_in,howManyRecos_in,isLocalStorAvailble_in,#this" />
<p:remoteCommand name="fetchFollowiesList" actionListener="#{recmdnsCntlr.fetchAllFollowiesList()}" process="#this" oncomplete="storeFollowiesList(args)"/>
</h:form>
<span id="editsForm" style="display:none">
<form action="javascript:void(0);" class="edits_submitter" >
<p:inputTextarea styleClass="editedText"/>
<input type="submit" value="Save edits"/>
<a class="cancel-edit" href="javascript:void(0)">Cancel</a>
</form>
</span>
</span>
A major con to the single, monolithic JSF form control is the sheer volume of data that is (needlessly) sent to the server for processing. Using your existing code. Consider the following. If all the controls in <h:form id="lobAction_form" > and <h:form id="comment_form" > were in a single form, you'd have
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
For every command action that you initiate in that form, possibly to process 1 input text component, you'd always be sending all 13 components in there to the server anyway. Wasteful and unnecessary. You'll have high volume of client-server communications for small operations and sometimes slow response times. Depending on whatever JSF framework you're using, you might be able to get creative with this situation, selectively processing components and what not, but that is just needless and painful. Clean separation of concerns also comes into play in the presentation layer.
Then there is the problem of validation. More often than not, you will have selected components in a single form that are marked as required and have nothing to do with the rest of the components within that form. You'll most likely be unable to selectively process those components without affecting all the other components on that form.
I see you're using primefaces. You could consider the use of Wizard component. With this component there is a single form with more sections in different tabs. The validation is done in Ajax mode when you go from one tab to the next one. As the partial validation is done with Ajax, only the fields of the tab you are validating, are processed and sent to the server.
It is also useful to split long forms in more readable and user friendly sections.

Resources