I have a jsf page that adds an order from a client.
All works fine except when I click the commandLink to show the p:dialog to add a new client the update on the "reste" inputtext stop working (even if I close the p:dialog without adding the new client) :
Clients List :
<strong>Client :</strong><
<p:autoComplete
id="client"
value="#{venteSolaireBean.client}"
completeMethod="#{venteSolaireBean.autocompleteClient}"
var="item"
itemLabel="#{item.nom} #{item.prenom}"
itemValue="#{item}"
converter="#{venteSolaireBean.clientConverter}"
dropdown="true"
scrollHeight="200" >
</p:autoComplete>
Link to a p:dialog to add a new Cleint :
<p:commandLink onclick="dlgClient.show()" immediate="true">
<img src="images-main/add-icon.gif" border="0" alt="Add Client" class="img-action"/>
</p:commandLink>
Three p:inputtext items with ajax behavior :
<strong>Montant :</strong>
<p:inputText value="#{venteSolaireBean.venteSolaire.montant}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Avance :</strong></td>
<p:inputText value="#{venteSolaireBean.venteSolaire.avance}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Reste :</strong></td>
<p:inputText id="reste" value="#{venteSolaireBean.venteSolaire.reste}">
</p:inputText>
The venteSolaireBean.calcul function to execute with the listener :
public void calcul() {
venteSolaire.setReste(venteSolaire.getMontant() - venteSolaire.getAvance());
}
I checked by logging the calcul() function and I'm sure it was invoked and the value giving to setReste() is correct.
I don't see why inputtext didn't update.
please help.
I think that there are some problems with the validation. As immediate=true often leads to such problems and you are not using any primefaces-functionality on the button to show the dialog, you should replace the p:commandButton with a plain HTML button to show the "add client"-dialog.
Related
I have a dropdown with ajax event to hide/show another component based on 'rendered' attribute.
It works fine, untill p:poll from another component gets invoked - the ajax event does not toggle the 'airportPickupWrapper' (although i can see the ajax request in Network)
component 1 :
<h:outputLink id="unresolvedOrdersCount" value="#{navigationMenuBean.setPage('management/orderManagement')}" style="color : red">
New orders : #{headerController.getUnresolvedOrdersCount()}
</h:outputLink>
<p:poll interval="10" update="unresolvedOrdersCount"/>
component2 :
<h:selectOneMenu id="orderTypeDropdown" value="#{orderController.order.orderType}">
<f:selectItems value="#{orderController.orderTypes}"
var="orderType"
itemLabel="#{orderType.displayName}">
</f:selectItems>
<p:ajax event="change" update="airportPickupWrapper"/>
</h:selectOneMenu>
<p:panel id="airportPickupWrapper" >
<h:panelGrid columns="1" rendered="#{orderController.order.orderType.name() == 'AIRPORT_PICKUP'}">
<p:outputLabel for="flightNumber" value="Flight number: " />
<p:inputText id="flightNumber" value="#{orderController.order.flightNumber}">
</p:inputText>
</h:panelGrid>
</p:panel>
thank you for suggestions
edit: if i change the component 1 so that it does not invoke backing bean, everything works fine
<h:outputLink id="unresolvedOrdersCount"></h:outputLink>
Solved.
The problem was i used h:outputLink, where xmlns:h="http://xmlns.jcp.org/jsf/html".
I switched it to p:link (xmlns:p="http://primefaces.org/ui") and everything works fine.
One would think it is compatible.
Thank you.
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.
I'm using JSF 2 and Primefaces 4 and have the following issue:
I've got the following code in my XHTML:
<h:form id="form">
<table>
<tr id="formats">
<td>Formats</td>
<td>
<p:selectBooleanCheckbox value="#{bean.entity.formatted}">
<p:ajax event="change" update="formatsSelect" />
</p:selectBooleanCheckbox>
<p:selectOneMenu id="formatsSelect" rendered="#{bean.entity.formatted}">
<f:selectItems value="#{bean.formats}" />
</p:selectOneMenu>
</td>
</tr>
</table>
</h:form>
It outputs a checkbox and a select menu and what I expect is that when I check the checkbox the select menu should appear and should disappear when I uncheck it.... but nothing happens, I check and uncheck it and the select menu is unaffected.
In theory this should work since the selectBooleanCheckbox value is bound to the entity.formatted boolean value and the rendered value in the selectOneMenu is bound to the entity.formatted value and the p:ajax points to the correct id in the update attribute and the event is correct. This last bit I know since I created a listener in my bean that printed the value of formatted:
public void changeListener(){
System.out.println(this.entity.isFormatted());
}
And changed the p:ajax to:
<p:ajax event="change" update="formatsSelect" listener="#{bean.changeListener}" />
And it printed the value of formatted in the console.
What am I doing wrong?
Since you used rendered on the component (p:selectOneMenu id="formatsSelect") and updating the same component, it wont work.
Because that component might not have been added to/present in component tree by the time you are updating.
So use a h:panelGroup around it and update it and use rendered on p:selectOneMenu.
<p:selectBooleanCheckbox value="#{bean.entity.formatted}">
<p:ajax event="change" update="formatsSelectPG" />
</p:selectBooleanCheckbox>
<h:panelGroup id="formatsSelectPG">
<p:selectOneMenu id="formatsSelect" rendered="#{bean.entity.formatted}">
<f:selectItems value="#{bean.formats}" />
</p:selectOneMenu>
</h:panelGroup>
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.
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" ...