jsf required=true destroys setPropertyActionListener? - jsf

Using primefaces 4.0 and jsf 2.2.5
stmt.xhtml has 2 includes. IncludeDetail.xhtml and IncludeDuo.xhtml. IncludeDuo also includes IncludeDetail.
In IncludeDetail.xhtml the <ui:composition> Element owns no <form>, id-Attribute or any other special elements. Only <h:panelGrid>, <h:selectOneMenu> and <h:selectOneMenu>. Nothing special.
IncludeDuo.xhtml owns <p:layout> and <p:message> as child elements of <ui:composition>. Deeper inside the <p:layout> we find this piece of code:
<h:panelGrid columns="1" style="padding-left: 10px">
<h:outputText value="AS" />
<h:selectManyMenu value="#{regelBean.selectedASForNewElement}" required="true" style="height:115px">
<f:selectItems value="#{aSBean.elementList}" var="var" itemLabel="#{var.vaSl}"
itemValue="#{var.vaSl}" />
</h:selectManyMenu>
</h:panelGrid>
If I remove required="true" everything works as expected. If I leave it there, the following setPropertyActionListener won't do it's job anymore:
<h:form id="form1">
<p:dialog header="Neue Regel" widgetVar="newDuoDialog" resizable="false" id="newDuoDlg" showEffect="fade"
hideEffect="fade" modal="true" styleClass="newDialog" width="1220">
<ui:insert name="insertDuo">
<ui:include src="/includes/duoRegelStmt.xhtml" />
</ui:insert>
</p:dialog>
<p:growl id="msgs" showDetail="true" life="20000"/>
<div class="nvg-dataTable">
<p:dataTable id="dt1" var="tVar" value="#{stmtBean.elementList}"
scrollable="false" styleClass="nvg-mainTable" paginator="true"
paginatorAlwaysVisible="false" rows="10"
rowsPerPageTemplate="10,25,100" paginatorPosition="bottom"
currentPageReportTemplate="({startRecord}-{endRecord} von {totalRecords})"
emptyMessage="Keine Statements gefunden" filteredValue="#{stmtBean.filteredElements}">
<p:column styleClass="padding2" style="width:6%">
<p:commandButton value="?" update=":dlgForm"
oncomplete="PF('detDialog').show()" icon="" title="Detail">
<f:setPropertyActionListener value="#{tVar}" target="#{stmtBean.selectedElement}" />
</p:commandButton>
<p:commandButton value="N" update=""
oncomplete="PF('newDuoDialog').show()" icon="" title="Neue Regel mit diesem Statement als Grundlage">
<f:setPropertyActionListener value="#{tVar}" target="#{stmtBean.selectedElement}" />
</p:commandButton>
[ ... ]
Is this a bug or am I misusing sth?

This is expected behaviour: As you are setting the property on submit of the form the property is only set when the form is successfully submitted, which is not the case when validation fails i.e. a required field is empty.
Use process="#this" on the p:commandButton so the form is not submitted. This should work for you as you just want to open the dialog and set the property.

Related

primefaces command button does not take action

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

Update Primefaces DataTable only if validation succeeds

Let's say as for an example, I have some input fields like,
<p:panel id="panel" closable="false" toggleOrientation="horizontal" toggleable="true" header="New">
<p:focus context="panel"/>
<p:watermark for="txtCountryName" value="Enter a valid country name."/>
<p:watermark for="txtCountryCode" value="Enter a valid country code."/>
<p:messages id="systemMessages" globalOnly="true" redisplay="false" showDetail="true" showSummary="true" autoUpdate="false" closable="true"/>
<p:messages id="specificSystemMessages" for="paramId" globalOnly="false" redisplay="false" showDetail="true" showSummary="false" autoUpdate="false" closable="true"/>
<h:panelGrid id="panelGrid" columns="3" cellpadding="5">
<p:outputLabel for="txtCountryName" value="Country"/>
<p:inputText id="txtCountryName" value="#{countryManagedBean.txtCountryName}" label="Country name" required="true" maxlength="45">
<f:validateLength minimum="2" maximum="45"/>
</p:inputText>
<p:message for="txtCountryName" showSummary="false"/>
<p:outputLabel for="txtCountryCode" value="Country Code"/>
<p:inputText id="txtCountryCode" value="#{countryManagedBean.txtCountryCode}" required="true" maxlength="45" label="Country code">
<f:validateLength minimum="2" maximum="45"/>
</p:inputText>
<p:message for="txtCountryCode" showSummary="false"/>
<p:commandButton id="btnSubmit" update="dataTable panel messages" actionListener="#{countryManagedBean.insert}" icon="ui-icon-check" value="Save"/>
</h:panelGrid>
</p:panel>
And a DataTable as follows.
<p:panel id="dataTablePanel" toggleable="true" toggleOrientation="horizontal" closable="false" header="Data">
<p:dataTable id="dataTable" var="row" value="#{countryManagedBean}"
lazy="true"
pageLinks="10"
paginator="true"
sortMode="multiple"
resizableColumns="true"
sortOrder="descending"
editable="true"
filterEvent="keyup"
selection="#{countryManagedBean.selectedValues}"
rowsPerPageTemplate="5,10,15"
rows="10"
rowKey="#{row.countryId}"
rowIndexVar="rowIndex"
rowStyleClass="#{row.countryId eq countryManagedBean.id? 'selected-data-row' : null}"
editMode="row">
...
...
...
</p:dataTable>
</p:panel>
When this command button,
<p:commandButton id="btnSubmit" update="dataTable panel messages" actionListener="#{countryManagedBean.insert}" icon="ui-icon-check" value="Save"/>
is clicked, a row is added to the underlying database, if it satisfies all of the validation rules and the DataTable is updated using the update="dataTable panel messages" attribute.
I would like updating this DataTable if and only if all the validation criteria as specified on these input fields are satisfied and the row is actually created.
If anyone of these validation rules fails, then this DataTable should not be updated anymore which is quite unnecessary and causes some costly JPA criteria and/or JPQL queries to be executed. Is this possible, how?
It is Primefaces 3.5.
Try using remotecommand in that case.
Change your submit button as shown below.
<p:commandButton id="btnSubmit" action="#{countryManagedBean.insert}" icon="ui-icon-check" value="Save" oncomplete="handleRequest(xhr, status, args)"/>
Add p:remoteCommand as shown below.
<p:remoteCommand name="updateTable" update="dataTable">
This remote command will be used for updating your table.
And yes, add below js.
<script type="text/javascript">
function handleRequest(xhr, status, args) {
if(!args.validationFailed) {
updateTable();
}
}
</script>
HTH
try to add this code to your bakedbean countryManagedBean at the end of the insert function or whereever you check the validation.
RequestContext context = RequestContext.getCurrentInstance();
context.addCallbackParam("validationFailed", "true");
This creates The callback param that you check with the javascript.

JSF Primefaces row value null in Edit popup window

I am using JSF 2.0 with Primefaces 3.4.2
For some strange reason I am not able to get the value in popup dialog window when a command button of row in datatable is clicked. Not sure what am I doing wrong?
Any help is highly appreciable.
I have the following in JSF page
<p:dataTable id="dataTable" var="emp" lazy="true"
value="#{myMB.lazyModel}"
selection="#{myMB.selectedEmployee}"...>
<p:column>
<p:commandButton id="edit" update=":frmedit:editDlg" process="#this"
onmousedown="dlg.show()" icon="ui-icon-pencil"
title="Edit" >
<f:setPropertyActionListener value="#{emp}"
target="#{myMB.selectedEmployee}" />
</p:commandButton>
</p:column>
Dialog code
<h:form id="frmedit">
<p:dialog header="Employees" style="font-weight:bold"
widgetVar=Dialog" resizable="false" id="dlg"
showEffect="fade" hideEffect="fade" appendToBody="true"
modal="true" width="200" height="250">
<h:panelGrid columns="2" cellspacing="5">
<h:outputText value="Employee #" />
<h:outputText value="#{myMB.selectedEmployee.empNo}"
style="font-weight:bold" />
</h:panelGrid>
And finally in ManagedBean
#Named("myMB")
#ViewAccessScoped
private Employee selectedEmployee= new Employee();
with getters and setters
Update 1
<p:column>
<p:commandButton id="edit" update=":frmedit:display" process="#this"
title="View"
icon="ui-icon-pencil" style="border-width:0;background:none;"
onmousedown="Dialog.show()">
<f:setPropertyActionListener value="#{emp}"
target="#{myMB.selectedEmployee}" />
</p:commandButton>
</p:column>
<p:dialog header="Employees" style="font-weight:bold"
widgetVar=Dialog" resizable="false" id="dlg"
showEffect="fade" hideEffect="fade" appendToBody="true"
modal="true" width="200" height="250">
<h:form id="frmedit">
<h:panelGrid id="display" columns="2" cellspacing="5">
<h:outputText value="Employee #" />
<h:outputText value="#{myMB.selectedEmployee.empNo}"
style="font-weight:bold" />
</h:panelGrid>
</h:form>
</p:dialog>
The three main reasons why this would be the case are
The dialog was not actually ajax updated
The property listener didn't set the value. You could easily debug this by adding some logging to the setter for that property
The bean was actually recreated and the selectedEmployee property was re-initialized per your
line:
Employee selectedEmployee= new Employee();
Per your comments on the previous answer, you should not have widgetVar and id for the same dialog having the same value
My vote is on (3). You should verify that the bean is not actually being trashed and recreated (constructor or #PostConstructor logging).
Try widgetVar="dlg" instead, in <p:dialog...> , according to this Example you should call
dialog from its widgetVar attribute
so dlg.show() refers to widgetVar="dlg" not the id

JSF2 - Primefaces - Partial update with command button not works when updating a nested panel

I’m trying to update a part of my page using the following command:
<p:commandButton id="bntNewAddress" immediate="true"
value="New Address" disabled="false" icon="ui-icon-document"
process="#this" update=":main_form:createPanelDetailsAddress"
action="#{issuerComponent.initAddNewAddress}">
</p:commandButton>
When I click the button, the panel "createPanelDetailsAddress" is not updated. On the other side when I use update=":main_form”, the panel is updated (but all other panels inside the main_form are updated also)
The panel I want to update is included in a panel named “createPanel”.
Could anyone have idea why update=":main_form:createPanelDetailsAddress" doesn't work in my case ?
I use primefaces3.5 and Mojarra JSF 2.1.7
Here is the code I used:
public String initAddNewAddress(){
renderCreatePanelDetailsAddress = true;
return null;
}
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" template="/template.xhtml">
<ui:define name="content">
<h:form id="main_form">
<p:panel id="createPanel" rendered="true">
<p:messages id="msgCreate" />
<p:panel id="createPanelDetails"
header="#{issuerMsgs['issuer.createArea.title']}">
<h:panelGrid border="0" columns="6">
<h:outputText value="#{issuerMsgs['issuer.issuerCode.title']}:" />
<p:inputText required="true"
value="#{issuerComponent.updateIssuer.issuerCode}"
label="issuer_issuerCode">
</p:inputText>
<h:outputText value="#{issuerMsgs['issuer.description.title']}:" />
<p:inputText required="true"
value="#{issuerComponent.updateIssuer.description}"
label="issuer_description">
</p:inputText>
</h:panelGrid>
</p:panel>
<p:spacer height="10" />
<p:panel id="panelListAddress"
header="#{addressMsgs['address.createArea.title']}">
<p:dataTable id="addresslist" var="address"
value="#{issuerComponent.addressList}" paginator="false" rows="10">
<p:column>
<f:facet name="header">
<h:outputText value="#{addressMsgs['address.tel.title']}" />
</f:facet>
<h:outputText value="#{address.tel}" />
</p:column>
</p:dataTable>
<p:spacer height="22" width="0" />
<p:commandButton id="bntNewAddress" immediate="true"
value="New Address" disabled="false" icon="ui-icon-document"
process="#this" update=":main_form:createPanelDetailsAddress"
action="#{issuerComponent.initAddNewAddress}">
</p:commandButton>
</p:panel>
<p:panel id="createPanelDetailsAddress"
header="#{addressMsgs['address.createArea.title']}"
rendered="#{issuerComponent.renderCreatePanelDetailsAddress}">
<ui:include src="createAddress.xhtml"></ui:include>
<p:commandButton value="Add"
rendered="#{issuerComponent.renderBtnAddAddress}" disabled="false"
icon="ui-icon-document" process="#this,createPanelDetailsAddress"
update=":main_form" action="#{issuerComponent.addNewAddress}"
actionListener="#{addressComponent.addNewComposite}">
<f:setPropertyActionListener
value="#{addressComponent.updateAddress}"
target="#{issuerComponent.address}" />
</p:commandButton>
</p:panel>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
Your update will fail because
rendered="#{issuerComponent.renderCreatePanelDetailsAddress}"
will evaluate to false the first time the view is rendered. As a result the component is not in the DOM tree the first time the view is rendered.
Ajax updates work by locating a specific component (by id) in the DOM and replacing it with new markup. Your panel was never in the DOM to begin with, so there's nothing to update with ajax.
To remedy, you need to wrap the <p:panel/>with another component and make that component the target of your ajax update
<p:outputPanel id="container" layout="none">
<p:panel id="createPanelDetailsAddress" header="# addressMsgs['address.createArea.title']}" rendered="#issuerComponent.renderCreatePanelDetailsAddress}">
<ui:include src="createAddress.xhtml"></ui:include>
<p:commandButton value="Add"
rendered="#{issuerComponent.renderBtnAddAddress}" disabled="false"
icon="ui-icon-document" process="#this,createPanelDetailsAddress"
update=":main_form" action="#{issuerComponent.addNewAddress}"
actionListener="#{addressComponent.addNewComposite}">
<f:setPropertyActionListener
value="#{addressComponent.updateAddress}"
target="#{issuerComponent.address}" />
</p:commandButton>
</p:panel>
</p:outputPanel>

f:setPropertyActionListener not invoked

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

Resources