How to update component on clientside in primefaces? - jsf

I want to create add children button with dialog form feature.
On the page there are tree and modal dialog form. On every node of tree will be the create child button. If you click on create child button, there will be shown modal form, where parentId will be set as id of node where button was clicked
Tree:
<h:form id="TestGroupListForm">
<p:tree value="#{testTreeController.root}" var="node" dynamic="true" cache="false"
selectionMode="single" selection="#{treeBean.selectedNode}" id="tree">
<p:treeNode>
<h:outputText value="#{node.getName()}" /> <p:commandButton id="createButton#{node.getIdTestGroup()}" icon="ui-icon-plus" value="#{bundle.Create}" update="tree" oncomplete="TestGroupCreateDialog.show()"/>
</p:treeNode>
</p:tree>
</h:form>
Dialog Box:
<h:form id="TestGroupCreateForm">
<h:panelGroup id="display">
<p:panelGrid columns="2" >
<p:outputLabel value="#{bundle.CreateTestGroupLabel_name}" for="name" />
<p:inputText id="name" value="#{testGroupController.selected.name}" title="#{bundle.CreateTestGroupTitle_name}" />
<h:inputHidden id="parentId" value="#{testGroupController.selected.parentId}" />
</p:panelGrid>
<p:commandButton actionListener="#{testGroupController.saveNew}" value="#{bundle.Save}" update="display,:TestGroupListForm:tree,:growl" oncomplete="handleSubmit(xhr,status,args,TestGroupCreateDialog);"/>
<p:commandButton value="#{bundle.Cancel}" onclick="TestGroupCreateDialog.hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
I want that click on
<p:commandButton id="createButton#{node.getIdTestGroup()}" icon="ui-icon-plus" value="#{bundle.Create}" update="tree" oncomplete="TestGroupCreateDialog.show()"/>
Will set value of:
<h:inputHidden id="parentId" value="#{testGroupController.selected.parentId}" />
UPDATE
I have to use action listener testGroupController.nodeListener to set parentId of the new item.
<p:commandButton process="#this" id="createButton" actionListener="#{testGroupController.nodeListener}" icon="ui-icon-plus" value="#{bundle.CreateGroup}" update=":TestGroupCreateForm" oncomplete="TestGroupCreateDialog.show()">
<f:attribute name="rawParentId" value="#{node.getIdTestGroup()}" />
</p:commandButton>

You can add parentId to the existing update= attribute like so:
update="tree parentId"
This will render parentId and set its value to testGroupController.selected.parentId.
Edit
You can process any values from the UI to the been too, by using:
process="myInputId"
Example
<h:form>
<h:inputText id="input"
value="#{bean.value}" />
<h:outputText id="output"
value="#{bean.value}" />
<p:commandButton process="input"
update="output"
value="Submit" />
Upon clicking your button, the value of id="input" will be set in bean.value (as ordered by process="input"). Next your id="output" will be rendered (or updated) with bean.value (as ordered by update="output").

Related

p:remoteCommand update attribute VS p:commandButton update attribute?

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

Keep p:dialog open when validation failed

I have a simple page with data table. Above the table theres a button to add a new table row. This button opens up a pop up form with the registration form. The object which is being created in that form has a bean validation set. Now when I submit an invalid form, the data is not added, a message is created and the pop up window is closed.
My problem is that I want to keep the pop up window open in case the validation is not passed.
The pop up window code:
<p:dialog header="New company registration" widgetVar="cmpRegDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false">
<p:outputPanel id="cmpRegistration" style="text-align:center;">
<h:panelGrid id="cmpRegistrationGrid" columns="3" columnClasses="label,value" cellpadding="5">
<p:outputLabel for="cmpNameR" value="Name:"/>
<p:inputText id="cmpNameR" value="#{companyBean.newCompany.name}" />
<p:message for="cmpNameR" />
<p:outputLabel for="cmpAddressR" value="Address:"/>
<p:inputText id="cmpAddressR" value="#{companyBean.newCompany.address}" />
<p:message for="cmpAddressR" />
<p:outputLabel for="cmpIcoR" value="ICO:"/>
<p:inputText id="cmpIcoR" value="#{companyBean.newCompany.ico}" />
<p:message for="cmpIcoR" />
<p:commandButton value="Submit" styleClass="secondary-btn flat" action="#{companyBean.registerNewCompany()}" update=":companyRegistrationForm :companiesOverviewForm"/>
<p:commandButton value="Reset" update="cmpRegistrationGrid" process="#this" style="margin-right:10px; width: auto;" styleClass="indigo-btn" >
<p:resetInput target="cmpRegistrationGrid" />
</p:commandButton>
</h:panelGrid>
</p:outputPanel>
</p:dialog>
Yep just add this to your "Submit" button oncomplete="if (!args.validationFailed) PF('#cmpRegDialog').hide();"
<p:commandButton value="Submit"
styleClass="secondary-btn flat"
action="#{companyBean.registerNewCompany()}"
update=":cmpRegistration :companiesOverviewForm"/>
oncomplete="if (!args.validationFailed) PF('#cmpRegDialog').hide();"
Basically only close the dialog if there was no validation failure. NOTE: Make sure not to update="" the form enclosing the dialog or else your dialog will close every time. You should only update the panel inside the dialog "cmpRegistration" like I have done above.

p:dialog appears on bottom when p:blockUI targets it

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>

how to reload p:dataGrid programmatically?

I have a datagrid with subscribe and unsubscribe option so the user can subscribe and unsubscribe and vise verse.
now I want to reload the datagrid after subscription or unsubscription
I load the data of the grid like that
#PostConstruct
public void init() {
packages = packagehelper.getAllPackages();
getCurrentUserSubscritions();
}
and here is the xhtml file
<h:form id="form">
<p:growl id="growl" showDetail="true" sticky="false" life="8000" />
<p:dataGrid var="package" value="#{packageView.packages}" columns="3"
>
<p:column>
<f:facet name="header">
Cars for Sale
</f:facet>
<p:panel header="#{package.id}" style="text-align:center">
<h:panelGrid columns="2" style="width:100%">
<p:graphicImage width="100px" name="images/#{package.imageurl}"/>
<h:outputText value="#{package.name}" />
<h:outputText value="#{package.value} EGP for #{package.duration} Days " />
<h:outputText value="#{package.description}" />
<p:commandButton ajax="true" update=":pack" value="Subscribe" rendered="#{!packageView.IsPackageActive(package.id)}" action="#{packageView.Subscribe()}" >
<f:setPropertyActionListener value="#{package.id}" target="#{packageView.packageID}" />
<f:setPropertyActionListener value="#{package.duration}" target="#{packageView.packageDuration}" />
</p:commandButton>
<p:commandButton action="#{packageView.Unsubscribe}" update=":pack" ajax="true" value="Cancel" rendered="#{packageView.UserHasPackage(package.id) and packageView.IsPackageActive(package.id) }">
<f:setPropertyActionListener value="#{package.id}" target="#{packageView.packageID}" />
<f:setPropertyActionListener value="#{package.duration}" target="#{packageView.packageDuration}" />
</p:commandButton>
</h:panelGrid>
</p:panel>
</p:column>
</p:dataGrid>
</h:form>
When an suscribe or unsuscribe action is completed, you should actualize the DataGrid trough its ID, it is, set an ID to the DataGrid and put such id in the update property of the buttons.
For example:
<p:dataGrid id="datalist" .../>
<p:commandButton action="#{packageView.Unsubscribe}" update="datalist" .../>
And when the action of the button is submited set the packages in null, so when the update action of the DataGrid update the packages they should be called again of the persistence or data base.
It is important to consider how to reference the elements in update property. You can see this answer

How to change the state of properties before event calls?

I am using this dialog to display a Create form
<p:dialog id="dialogoGestion" header="Asignar nueva gestión" widgetVar="dlg1" >
<p:ajax event="close" update="dialogoGestion"/>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Cliente: "/>
<h:outputText value="#{miscMB.factura.cliente.nombre}"/>
<h:outputText value="Factura: "/>
<h:outputText value="#{miscMB.factura}"/>
<h:outputLabel value="#{bundle.CreateGestionLabel_descripcion}" for="descripcion" />
<p:inputText id="descripcion" value="#{miscMB.nuevaGestion.descripcion}" title="#{bundle.CreateGestionTitle_descripcion}" />
<h:outputLabel value="#{bundle.CreateGestionLabel_fechaLimiteGestion}" for="fechaLimiteGestion" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaLimiteGestion" value="#{miscMB.nuevaGestion.fechaLimiteGestion}" title="#{bundle.CreateGestionTitle_fechaLimiteGestion}" required="true" requiredMessage="#{bundle.CreateGestionRequiredMessage_fechaLimiteGestion}">
</p:calendar>
<h:outputLabel value="#{bundle.CreateGestionLabel_usuario}" for="usuario" />
<p:selectOneMenu id="usuario" value="#{miscMB.nuevaGestion.usuario}" required="true" requiredMessage="#{bundle.CreateGestionRequiredMessage_usuario}">
<f:selectItems value="#{usuarioController.itemsAvailableSelectOne}"/>
</p:selectOneMenu>
</h:panelGrid>
<br />
<p:commandButton onsuccess="micalendario.update();PF('dlg1').hide();" action="#{gestionController.crearGestion()}" value="#{bundle.CreateGestionSaveLink}" >
<f:setPropertyActionListener target="#{gestionController.selected}" value="#{miscMB.nuevaGestion}"/>
<f:setPropertyActionListener target="#{gestionController.factura}" value="#{miscMB.factura}"/>
<f:setPropertyActionListener value="#{null}" target="#{miscMB.nuevaGestion}"/>
<f:actionListener binding="#{miscMB.anularNuevaGestion()}"/>
<f:actionListener binding="#{miscMB.agregarGestion(gestionController.selected)}"/>
</p:commandButton>
</h:form>
</p:dialog>
This is where I call the dialog to display
<p:commandLink value="Asignar gestión" onclick="PF('dlg1').show();return false;" action="#{gestionController.preparar()}" rendered="#{miscMB.factura!=null}">
<f:setPropertyActionListener target="#{gestionController.factura}" value="#{miscMB.factura}"/>
</p:commandLink>
What happens is that both <h:outputText value="#{miscMB.factura.cliente.nombre}"/> and <h:outputText value="#{miscMB.factura}"/> values display the properties' last state.
For example, the first time an item selected and you call the dialog, the output is none, because the state is not set. Then, when you select another item and call the dialog, the output is the state last set, which is the previous item value.
Apparently, the setPropertyActionListener in the commandLink is called after the dialog is closed or it executes an action, but not when the commandLink is clicked.
So, how can I set the properties before the dialog frame is displayed?

Resources