JSF Ajax reset previously rendered input component values? - ajax

I have a small (but vital) problem with JSF and ajax. The form is here:
<h:form>
<h:panelGrid id="pg1" columns="2">
<h:outputText value="Type: "/>
<h:selectOneMenu id="selectOne" value="#{personBean.type}">
<f:selectItems value="#{listBean.personTypes}"/>
<f:ajax event="valueChange" render="pg2"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGrid id="pg2" columns="2">
<h:outputText value="Really bad?" rendered="#{personBean.type=='BAD'}"/>
<h:selectBooleanCheckbox id="checkbox" value="#{personBean.reallyBad}" rendered="#{personBean.type=='BAD'}">
<f:ajax event="click"/>
</h:selectBooleanCheckbox>
</h:panelGrid>
<h:commandButton value="Ajax Submit" action="#{personBean.printValues}">
<f:ajax execute="#form"/>
</h:commandButton>
</h:form>
The PersonBean is a simple bean with an enum PersonType that has two values: NICE, BAD and a Boolean called reallyBad. The ListBean returns the enum values in a list to populate the selectOneMenu.
Basically when I select BAD the panel for the boolean checkbox is rendered where I can tick it to say a person is reallyBad. I can then submit the form if I wish. The problem is when I tick the checkbox and then select NICE again, the checkbox is still ticked even though it is not rendered. So when I submit my form the person can be NICE and reallyBad, which doesn't make sense.
Rather than having to select BAD again to uncheck the box, is their a way that I can reset the checkbox and its input value to false when NICE is selected? I'm a bit of a noob to ajax with JSF! Thanks.
ps. I am printing the values of the two inputs on submit with the commandButtons action to verify the results...

You need to manually clear the checkbox when you change the menu.
<f:ajax listener="#{personBean.setReallyBad(false)}" render="pg2" />
By the way, the both <f:ajax event> values as you've in your code are the default values already. Just omit them.

Related

What is the difference b/w #form value and explicitly mentioning the component Ids in render attribute of <f:ajax>?

Consider the snippet:
<h:form>
<hr/>
<h:panelGrid columns="3">
Name:
<h:inputText id="nameId" value="#{ajaxBean.name}"
validator="nameValidator"
f5:placeholder="Enter your name ..."/>
<h:message id="msgNameId" showDetail="true"
showSummary="true" for="nameId"
style="color: red;"/>
Surname:
<h:inputText id="surnameId" value="#{ajaxBean.surname}"
validator="nameValidator"
f5:placeholder="Enter your surname ..."/>
<h:message id="msgSurnameId" showDetail="true"
showSummary="true" for="surnameId"
style="color: red;"/>
</h:panelGrid>
<h:commandButton value="Submit">
<f:ajax execute="#form"
render="#form" listener="#
{ajaxBean.upperCaseNameAndSurname()}"/
</h:commandButton>
<h:commandButton value="Cancel">
<f:ajax execute="#this"
render="#form"/>
</h:commandButton>
<h:commandButton value="Clear/Reset">
<f:ajax execute="#this"
render="#form"
listener="#{ajaxBean.cancelNameAndSurname()}"/>
</h:commandButton>
</h:form>
resetValues= "true" seems to work only if one mentions the component ids explicitly inside the render attribute of the <f:ajax> for the Submit button.
i.e render="nameId msgNameId surnameId msgSurnameId" rather than render="#form"
What exactly is the difference b/w these 2 forms?
The invalid values are still there after re-render if the value is (#form) for render attribute for Submit button.
I definitely remembered one of the comments by BalusC,
When validations phase has failed due to a conversion or validation
error anywhere, components which successfully passed validation will
return local value and components which failed validation will return
submitted value.
If the name is valid and the surname is not (or any other combination involving invalid values), then after submit and clear/ reset, the input field*(i.e the valid field)* for the name is not cleared. Even though the whole form was re-rendered, I see only the field for which validation failed was cleared. Why?
Does the above comment signifies some relation with the above problem?
The cancelNameAndSurname method just do this thing-
name = ""
surname = ""
I know for sure that one of the solutions to resolve this is -
<f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener"/>

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.

h:panelGroup not rendered when change the value of h:selectOneMenu using AJAX

I have a grid group that should be rendered when change the value of the selectOneMenu. I have attached a valueChangeListener to the selectOneMenu and it access succefully the function assigned to it , but the html component does not rerender. the strange thing that the flag the determines the rendering is called anyway.
<h:selectOneMenu value="#{channelsAdmin.profileID}" id="profileDrp" valueChangeListener="#{channelsAdmin.setProfileInit}">
<f:selectItems value="#{channelsAdmin.profiles}" var="Profile"
itemLabel="#{Profile.profileName}"
itemValue="#{Profile.profileId}" />
<f:ajax execute="#this" immediate="true" render="pnl"></f:ajax>
</h:selectOneMenu>
<h:panelGroup id="pnl" rendered="#{channelsAdmin.ccpAuthPanelFlage}">
<h:inputText id="sest" value="hew">
</h:inputText>
</h:panelGroup>
Bean:
public void setProfileInit(ValueChangeEvent e) {
ccpAuthPanelFlage=true;
ccpPurchPanelFlage=true;
}
The <f:ajax render="pnl"> works roughly as follows:
When the ajax response is arrived, obtain the update element with id="pnl" from XML response.
Now obtain the element with id="pnl" from HTML document by document.getElementById().
Replace its contents with the update element from XML response.
In your particular case, step 2 failed because there's no such element in the HTML document. It doesn't exist in the HTML document because it's never been rendered in first place.
You need to make sure that <f:ajax render="..."> refers an element which is always rendered so that JavaScript can find it by document.getElementById() in order to replace its contents.
<h:selectOneMenu value="#{channelsAdmin.profileID}" id="profileDrp" valueChangeListener="#{channelsAdmin.setProfileInit}">
<f:selectItems value="#{channelsAdmin.profiles}" var="Profile"
itemLabel="#{Profile.profileName}"
itemValue="#{Profile.profileId}" />
<f:ajax execute="#this" immediate="true" render="pnl"></f:ajax>
</h:selectOneMenu>
<h:panelGroup id="pnl">
<h:panelGroup rendered="#{channelsAdmin.ccpAuthPanelFlage}">
<h:inputText id="sest" value="hew">
</h:inputText>
</h:panelGroup>
</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?

understanding ajax execute behavior with datatable using jsf 2.0

i'm trying to use an search button which brings back the selected items (can be more than one) and it updates the datatable. Then i have a selectBooleanCheckbox next to each colomn, when user selects "n" items then presses the Select the checked Items it insert DB.
The code can be seen below:
<h:panelGrid columns="5">
<h:form>
<h:outputText value="Item Name"/>
<p:inputText value="#{StockController.itemName}"/>
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
//The code sample below belongs to BalusC see the post here
<h:panelGroup id="results">
<h:form>
<h:dataTable value="#{bean.entities}" var="entity">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[entity.id]}" />
</h:column>
...
</h:dataTable>
<h:commandButton value="Select the checked Items" action="#{StockController.insertDao}" >
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
</h:panelGrid>
Now, i have read many blogs and Core javaServer Faces 3, i don't think there is logical error in ajax usage. I tested by removing each ajax then both works fine but whenever i try to use both of cummondButtons with ajax, the second one "Select the checked Items" does not even call the "StockController.insertDao" method.
Any help is appreciated.
Thanks all.
When you want to ajax-render content which in turn contains another form, then you need to include the ID of that form in the render attribute as well, otherwise the other form will lose its view state and nothing will be processed on submit.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results :resultsForm" />
</h:commandButton>
</h:form>
<h:panelGroup id="results">
<h:form id="resultsForm">
...
</h:form>
</h:panelGroup>
If there's however nothing which goes outside <h:form> inside the same <h:panelGroup>, then you can just omit the <h:panelGroup> altogether and re-render the form directly.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results" />
</h:commandButton>
</h:form>
<h:form id="results">
...
</h:form>
This is related to JSF spec issue 790.
See also:
Communication in JSF2 - Ajax rendering of content which contains another form

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

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

Resources