i have a problem with the display of a dialog on a click. It's a obvious one but i can't spot the bug. I've been stuck on this for days, it's crazy. Can you help me please.
<h:form id="form">
<p:commandButton
rendered="#{characterBean.characterSession.characterName ne null}"
value="#{characterBean.characterSession.title.titleName}"
icon="fa fa-fw fa-edit" onclick="PF('dlg').show();"
update="#form"/>
<p:dialog id="titleDetail" header="#{i18n['title.yourTitles']}"
widgetVar="dlg" dynamic="true" closable="false" resizable="false"
showEffect="fade" hideEffect="fade">
<h:panelGroup>
<p:messages autoUpdate="true" />
<h:selectOneMenu id="titleSelect" converter="#{titleConverter}"
value="#{characterBean.characterSession.title}">
<f:selectItems value="#{characterBean.titleUnlocked}" var="t"
itemValue="#{t}" itemLabel="#{t.titleName}" />
</h:selectOneMenu>
<hr />
<h:panelGrid columns="2" style="width: 100%; text-align:center">
<p:commandButton value="#{i18n['general.submit']}"
icon="fa fa-check"
actionListener="#{characterBean.updateCharacterTitle}"
oncomplete="PF('dlg').hide();" update="#form" />
<p:commandButton value="#{i18n['general.cancel']}"
icon="fa fa-close" action="#{characterBean.submitCancel}"
oncomplete="PF('dlg').hide();" update="#form" process="#this" />
</h:panelGrid>
<p:remoteCommand name="updateForm()" process="#this" update="#form" />
</h:panelGroup>
</p:dialog>
</h:form>
The core problem is essentially this:
<h:form>
<p:commandButton onclick="PF('dlg').show();" update="#form"/>
<p:dialog widgetVar="dlg">
...
</p:dialog>
</h:form>
The default state of <p:dialog> is hidden.
The onclick shows the dialog.
The update updates the entire content of the <h:form>.
The <p:dialog> is also included in the update.
So, the <p:dialog> gets hidden again.
There are several solutions:
Don't let update include the <p:dialog>.
<h:form>
<h:panelGroup id="outsideDialog">
<p:commandButton onclick="PF('dlg').show();" update="outsideDialog"/>
</h:panelGroup>
<p:dialog widgetVar="dlg">
...
</p:dialog>
</h:form>
Replace onclick by oncomplete as it runs after the update.
<h:form>
<p:commandButton update="#form" oncomplete="PF('dlg').show();" />
<p:dialog widgetVar="dlg">
...
</p:dialog>
</h:form>
Move <p:dialog> outside the <h:form> and give it its own <h:form>.
<h:form>
<p:commandButton update="#form :dlg" oncomplete="PF('dlg').show();" />
</h:form>
<p:dialog id="dlg" widgetVar="dlg">
<h:form>
...
</h:form>
</p:dialog>
or, depending on whether you actually need to update the dialog's contents or not
<h:form>
<p:commandButton onclick="PF('dlg').show();" update="#form" />
</h:form>
<p:dialog widgetVar="dlg">
<h:form>
...
</h:form>
</p:dialog>
The recommended solution is 3.
See also:
Execution order of events when pressing PrimeFaces p:commandButton
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
p:commandbutton action doesn't work inside p:dialog
Related
I have the following block of code, when i update the "pickList" from the p:remoteCommand it gets updated.
<h:panelGrid columns="1">
<p:panel id="panel" header="Units"
style="margin-bottom:10px; background:#F3F2F2; margin-bottom:0px">
<p:pickList id="pickList"
value="#{AdminController.unitsPickListAll}" var="selectedUnit"
itemLabel="#{selectedUnit}" itemValue="#{selectedUnit}" />
</p:panel>
<h:panelGrid columns="1" styleClass="right-alignment">
<h:panelGroup>
<p:commandButton id="refereshButton" value="#{i18n.refresh}"
immediate="true" action="#{AdminController.getAllUnits}"
oncomplete="rc()" />
<h:outputText value=" " />
<p:commandButton id="saveButton" value="#{i18n.save}"
action="#{AdminController.updateUsedUnits}" />
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
<p:remoteCommand name="rc" update="panel" />
But when I use "update" attribute in the "refereshButton", the pickList does not get updated.
Below is the same code but without p:remoteCommand and with update attribute in refereshButton.
<h:panelGrid columns="1">
<p:panel id="panel" header="Units"
style="margin-bottom:10px; background:#F3F2F2; margin-bottom:0px">
<p:pickList id="pickList"
value="#{AdminController.unitsPickListAll}" var="selectedUnit"
itemLabel="#{selectedUnit}" itemValue="#{selectedUnit}" />
</p:panel>
<h:panelGrid columns="1" styleClass="right-alignment">
<h:panelGroup>
<p:commandButton id="refereshButton" value="#{i18n.refresh}"
immediate="true" action="#{AdminController.getAllUnits}"
update="pickList" />
<h:outputText value=" " />
<p:commandButton id="saveButton" value="#{i18n.save}"
action="#{AdminController.updateUsedUnits}" />
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
What this reason behind this behavior?
The reason you are getting different results is because you are doing different updates. You update panel from the remote command and pickList from the button.
Use update="panel" on your button to get the same result. This will also save you an Ajax request (and some server load).
I have a dialog which is contains two listboxes, one checkbox and one button. I try to pass values of these components to backing bean.
<p:dialog header="Add" widgetVar="dlgAdd" resizable="false"
id="dlgAddId" showEffect="fade" modal="true">
<h:form id="dlgAddForm">
<p:panelGrid columns="2">
<p:outputLabel>Name*</p:outputLabel>
<p:selectOneMenu id="addname" value="#{notificationsSettingManagedBean.customerUserEmailSetting.userNameSurname}" effect="fold">
<f:selectItems value="#{notificationsSettingManagedBean.customerUserNameSurnameList}" />
</p:selectOneMenu>
<p:outputLabel>Email-ID*</p:outputLabel>
<p:selectOneMenu id="addsurname" value="" effect="fold">
<f:selectItems value="#{notificationsSettingManagedBean.customerUserEmailsList}" />
</p:selectOneMenu>
</p:panelGrid>
<p:panel>
<div align="center">
<p:outputLabel>Email Notifications</p:outputLabel>
</div>
</p:panel>
<p:panelGrid columns="2" style="width: 100%;text-align: center;">
<p:outputLabel>Order Submitted</p:outputLabel>
<p:selectBooleanCheckbox value="#{notificationsSettingManagedBean.customerUserEmailSetting.orderSubmit}"/>
</p:panelGrid>
<div align="center">
<p:commandButton
actionListener="#{notificationsSettingManagedBean.saveCustomerEmailSettings}"
immediate="true" value="Save" ajax="true"
oncomplete="dlgAddId.hide();" />
</div>
</h:form>
</p:dialog>
On notificationsSettingManagedBean, i create customerUserEmailSetting object which is contains get and set methods of userNameSurname,customerUserEmailsList and ordersubmit.
Problem is when try to get this data on saveCustomerEmailSettings method on backing bean i see that these data are null. How can i pass them to backing bean?
i need help with this. I have a 'form' which call a p:dialog through p:commandButton. That p:dialog include other p:commandButton, but that second button does not take any action, which is weird for me, because the first button works fine.
The code:
<ui:define name="body">
<br/>
<br/>
<br/>
<p:ajaxStatus onstart="PF('statusDialog').show()" onsuccess="PF('statusDialog').hide()" />
<p:dialog widgetVar="statusDialog" modal="true" draggable="false" closable="false" resizable="false" showHeader="false">
<p:graphicImage value="/resources/Images/ajax-loader.gif" alt="Por favor espere..." />
</p:dialog>
<h:form id="BuscarEmpresaForm">
<h:panelGroup id="display">
<h:panelGrid columns="2" style="margin-left: 10px;">
<p:outputLabel value="#{bundle.BuscarEmpresaBuscarLabel}" />
<h:outputLabel/>
<h:selectOneRadio id="idBusquedaRadio" value="#{cupoController.radioButtonBusqueda}">
<f:selectItem itemLabel="#{bundle.BuscarEmpresaCodigoLabel}" itemValue="Codigo" />
<f:selectItem itemLabel="#{bundle.BuscarEmpresaNombreLabel}" itemValue="Nombre" />
</h:selectOneRadio>
<h:outputLabel/>
<p:inputText id="empresa" value="#{cupoController.empresaTextoBusqueda}" required="true" requiredMessage="El campo es requerido"/>
<!--THIS BUTTON WORKS-->
<p:commandButton value="Buscar" actionListener="#{cupoController.prepareCreateEmpresa()}" action="#{cupoController.searchEmpresa()}" oncomplete="PF('dlg1').show();" update=":confirmDialogEmpresa">
</p:commandButton>
<p:message for="empresa"/>
</h:panelGrid>
</h:panelGroup>
</h:form>
<p:dialog id="dialog1" header="Mensaje" widgetVar="dlg1" minHeight="40" modal="true" appendTo="#(body)">
<h:form id="confirmDialogEmpresa">
<h:panelGroup id="display">
<h:panelGrid columns="2" rendered="#{cupoController.selectedEmpresa.codcor != null}">
<p:outputLabel value="Empresa encontrada, Continuar?"/>
<h:outputLabel/>
<p:outputLabel value="Nombre: #{cupoController.selectedEmpresa.razonsocial}"/>
<h:outputLabel/>
<p:outputLabel value="RUC: #{cupoController.selectedEmpresa.ruc}"/>
<h:outputLabel/>
<!--THIS BUTTON DOES NOT WORK-->
<p:commandButton value="Si" action="#{cupoController.buscarCupo}" icon="ui-icon-check"/>
<p:commandButton value="No" onclick="dlg1.hide();" icon="ui-icon-close" update="#none"/>
</h:panelGrid>
<h:panelGrid columns="2" rendered="#{cupoController.selectedEmpresa.codcor == null}" >
<p:outputLabel value="Empresa no encontrada"/>
<h:outputLabel/>
<p:messages />
<h:outputLabel/>
<p:commandButton value="Aceptar" onclick="dlg1.hide();" icon="ui-icon-close" update="#none"/>
</h:panelGrid>
</h:panelGroup>
</h:form>
</p:dialog>
</ui:define>
I have done some attempts replacing p:commandButton for h:commandButton but have same results.
An image showing what code outs
Thanks in advance.
I found the problem and is related to the topic: Backing beans (#ManagedBean) or CDI Beans (#Named)?
In my case i was confused. I was mixing CDI annotations with JSF annotations in the managed bean related, producing a strange behavior. Finally i have fixed letting just JSF annotations.
Core: JSF 2.0, PrimeFaces 5.0, GlassFish 4.1
I have a PrimeFaces dialog, that has two command buttons that executes some code in the backing bean. I want to block the dialog within the action.
I managed to do it using blockUI, but when the blockUI is present, and I open the dialog, it appears at the bottom of the page.
If I remove the blockUI component, the dialog opens at the center of the page, as I want. But I want it to be centered and with the blockUI.
<p:dialog header="Attention" id="dialog" position="center"
widgetVar="dialog" modal="true" closable="false"
dynamic="true" closeOnEscape="false">
<div class="internal-margin-top">
<h:outputText value="Location" styleClass="ui-outputtext" />
<p:inputText value="#{activityBean.location}"
id="inputLocation" maxlength="15">
</p:inputText>
</div>
<div class="internal-margin-bottom">
<p:commandButton id="closureYes" value="Yes"
styleClass="btn-green"
onstart="PF('block').show();"
oncomplete="PF('dialog').hide(); PF('block').hide();"
action="#{activityBean.processItem()}" process="#all">
</p:commandButton>
<p:commandButton id="closureNo" value="No"
styleClass="btn-red"
onstart="PF('block').show();"
oncomplete="PF('dialog').hide(); PF('block').hide();"
action="#{activityBean.processActivity()}" process="#all" />
</div>
</p:dialog>
<p:blockUI block="scrapDialog" widgetVar="block">
<p:graphicImage library="images" name="loading_bar.gif" />
</p:blockUI>
Thanks in advance.
Example with a centered modal dialog:
<p:dialog header="Header" position="center" widgetVar="wv_dialog" modal="true" closable="false" dynamic="true" closeOnEscape="false">
<h:form id="dialogform">
<p:panelGrid columns="1">
<p:inputText value="test"/>
<p:inputText value="test"/>
<p:inputText value="test"/>
<p:inputText value="test"/>
</p:panelGrid>
<p:commandButton id="closebutton"
value="Close"
oncomplete="PF('wv_dialog').hide();"
action="#{testBean.actionTest()}"
process="#form"/>
<p:blockUI block="dialogform" trigger="closebutton"/>
</h:form>
</p:dialog>
I am trying to move a p:dialog out of a h:form, because I have read that this is the preferred way (however I'd like to understand the reason, because my p:dialog inside a form works well in my application).
The only difficulty is that the dialog title needs to be updated dynamically. The dialog is shown when a button in a p:dataTable is clicked.
Here is my old xhtml (before the changes), that's working fine:
<p:dataTable var="event" value="#{eventBean.lazyModel}" selection="#{eventBean.selectedEvent}" />
...
<p:column headerText="#{msgs.Persons}">
<p:commandButton value="#{msgs.ViewPersons}" update=":viewPersonsForm" oncomplete="viewPersonsDlg.show()">
<f:setPropertyActionListener value="#{event}" target="#{eventBean.selectedEvent}" />
</p:commandButton>
</p:column>
</p:dataTable>
<h:form id="viewPersonsForm">
<p:dialog modal="true" widgetVar="viewPersonsDlg" dynamic="true" header="#{eventBean.selectedEvent.name}" >
...
</p:dialog>
</h:form>
And here is the new xhtml, with eventBean#setSelectedEvent() that is not invoked.
<p:dataTable var="event" value="#{eventBean.lazyModel}" selection="#{eventBean.selectedEvent}" />
...
<p:column headerText="#{msgs.Persons}">
<p:commandButton value="#{msgs.ViewPersons}" update=":viewPersonsDlgId" oncomplete="jQuery('#viewPersonsDlgId .ui-dialog-title').text('#{eventBean.selectedEvent.name}');viewPersonsDlg.show()">
<f:setPropertyActionListener value="#{event}" target="#{eventBean.selectedEvent}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog modal="true" id="viewPersonsDlgId" widgetVar="viewPersonsDlg" dynamic="true" >
...
</p:dialog>
So, again, why in the second scenario eventBean#setSelectedEvent() is not invoked? And, if possible, why the first scenario is not optimal?
It is not restricted to use p:dialog inside a h:form since it can work in some cases, but most of the time you will find yourself struggling with some unexpected behaviour with that, here are some explanations :
Why not to place p:dialog inside h:form 1
Why not to place p:dialog inside h:form 2
The problem in your case is that jQuery method in oncomplete is called before the value is set with f:setPropertyActionListener. To avoid this use the same solution as you used in your first case. So :
<p:dataTable var="event" value="#{eventBean.lazyModel}" selection="#{eventBean.selectedEvent}" />
...
<p:column headerText="#{msgs.Persons}">
<p:commandButton value="#{msgs.ViewPersons}" update=":viewPersonsDlgId" oncomplete="viewPersonsDlg.show()">
<f:setPropertyActionListener value="#{event}" target="#{eventBean.selectedEvent}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog modal="true" id="viewPersonsDlgId" widgetVar="viewPersonsDlg" dynamic="true" header="#{eventBean.selectedEvent.name}" >
...
</p:dialog>
No need to use jQuery here.
I had the same problem (pf 3.5):
<p:tabView id="cashFlowTabContainer" style="width:100%" activeIndex="0"
widgetVar="cashFlowTabContainerVar">
<p:tab title="#{labels['cashflow_incoming']}">
<p:outputPanel id="incomingPanel">
<p:dataTable value="#{cashFlowController.incomingCashFlows}"
var="cashFlow">
<p:column headerText="#{labels.cashflow_actions}">
<p:commandButton value="Edit"
action="# {cashFlowController.editIncoming}" update="#form" oncomplete="editInputVar.show();">
<f:setPropertyActionListener value="#{cashFlow}"
target="#{cashFlowController.selectedIncoming}" />
</p:commandButton>
</p:column>
and this was my dialog:
<p:dialog id="editInput" header="Dynamic Dialog"
widgetVar="editInputVar" resizable="false" draggable="false"
modal="true">
<p:panel>
<h:panelGrid columns="2" cellpadding="5">
...
<h:outputText value="#{labels.cashflow_description}:" />
<h:inputText
value="#{cashFlowController.selectedIncoming.description}" />
So... This way the setter was NEVER called. Then I noticed that if I emptied the dialog the setter was called.
So I solved it by putting a "rendered" statement on the panel:
<p:dialog id="editInput" header="Dynamic Dialog"
widgetVar="editInputVar" resizable="false" draggable="false"
modal="true">
<p:panel **rendered="#{cashFlowController.selectedIncoming != null}"**>
<h:panelGrid columns="2" cellpadding="5">
I guess there's a null pointer that is not logged anywhere... anyway this way it works :)