Create edit form for Primefaces table - jsf

I want to create edit form for Primefaces table. I tested this code:
<h:form id="form">
<p:dataTable id="tbl" var="systemuser" value="#{systemusers.systemUsers}"
selectionMode="single" selection="#{systemusers.selectedSystemUser}" rowKey="#{systemuser.username}" lazy="true"
resizableColumns="true"
>
<p:ajax event="rowSelect" listener="#{systemusers.onRowSelect}" update=":form:carDetail" oncomplete="PF('carDialog').show()" />
....................
</p:dataTable>
<p:dialog id="wd" header="System User Details" widgetVar="carDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="true">
<p:outputPanel id="carDetail" style="text-align:center;">
<p:panelGrid columns="2" columnClasses="label,value">
<h:outputLabel for="id" value="ID" />
<p:outputLabel id="id" value="#{systemusers.selectedSystemUser.id}" rendered="#{not systemusers.editable}"/>
<h:inputText value="#{systemusers.selectedSystemUser.id}" rendered="#{systemusers.editable}" />
........
</p:panelGrid>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Edit System User" rendered="#{not systemusers.editable}"
actionListener="#{systemusers.editRecord(false)}">
<f:ajax render=":form:wd" execute=":form:wd"></f:ajax>
</p:commandButton>
<p:commandButton value="Cancel" rendered="#{systemusers.editable}" actionListener="#{systemusers.editRecord(true)}">
<f:ajax render=":form" execute=":form"></f:ajax>
</p:commandButton>
</f:facet>
</p:dialog>
<p:contextMenu for="tbl">
<p:menuitem value="View" update="carDetail" icon="fa fa-search" oncomplete="PF('carDialog').show()"/>
<p:menuitem value="Delete" update="tbl" icon="fa fa-remove" actionListener="#{systemusers.deleteSystemUser}">
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-warning" />
</p:menuitem>
</p:contextMenu>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="fa fa-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="fa fa-remove" />
</p:confirmDialog>
</h:form>
Managed bean:
#Named
#RequestScoped
public class Systemusers implements Serializable
{
.......
public void editRecord(boolean editable)
{
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try
{
session.getTransaction().begin();
SystemUsersModel obj = new SystemUsersModel();
obj.setId(selectedSystemUser.getId());
..........
session.update(obj);
session.getTransaction().commit();
this.editable = editable;
}
catch (Exception e)
{
e.printStackTrace();
session.getTransaction().rollback();
}
}
......
private boolean editable = false;
public boolean isEditable()
{
return editable;
}
public void setEditable(boolean editable)
{
this.editable = editable;
}
}
When I open the Edit form and I click button Edit System User the form disappears. Probably because I render and execute it. How I can execute the form and under it without closing it?

The example code is bad in multiple ways. Two things stand out:
It is not an [mcve]
<f:ajax render=":form" execute=":form"> is superfluous or might even cause the weird behaviour
OP most likely does not know that (quote from the PrimeFaces showcase , emphasis mine)
CommandButton
CommandButton extends the standard h:commandButton with ajax, partial processing and skinning features.
So the commandBotton is already ajax anabled and does not need to hava a
<f:ajax render=":form" execute=":form">
inside it. This (most likely) makes an the update run twice. One #none (Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes) and one updating the form. The second one most likely does not have any content. But trying (and debugging) will make things clear. If this is not the answer, the reason cannot be seen in the code and hence it should have been a [mcve]

Related

Primefaces command button event is not invoked

In Primefaces, a button will call a prepareCreate method and then open the form dialog. The issue is, this method never get called so that the form in the dialog is not shown.
Command button
<p:commandButton id="createButton1" value="#{bundle.Create}" actionListener="#{purchaseOrderController.prepareCreate}"
update=":PurchaseOrderCreateForm11" oncomplete="PF('PurchaseOrderCreateDialog11').show()"/>
Dialog
<p:dialog id="PurchaseOrderCreateDlg11" widgetVar="PurchaseOrderCreateDialog11" modal="true" resizable="false" appendTo="#(body)" header="#{bundle.CreatePurchaseOrderTitle}">
<h:form id="PurchaseOrderCreateForm11">
<h:panelGroup id="display">
<p:panelGrid columns="2" rendered="#{purchaseOrderController.selected != null}">
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_orderNum}" for="orderNum" />
<p:inputText id="orderNum" value="#{purchaseOrderController.selected.orderNum}" title="#{bundle.CreatePurchaseOrderTitle_orderNum}" required="true" requiredMessage="#{bundle.CreatePurchaseOrderRequiredMessage_orderNum}"/>
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_quantity}" for="quantity" />
<p:inputText id="quantity" value="#{purchaseOrderController.selected.quantity}" title="#{bundle.CreatePurchaseOrderTitle_quantity}" />
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_shippingCost}" for="shippingCost" />
<p:inputText id="shippingCost" value="#{purchaseOrderController.selected.shippingCost}" title="#{bundle.CreatePurchaseOrderTitle_shippingCost}" />
</p:panelGrid>
<p:commandButton actionListener="#{purchaseOrderController.create}" value="#{bundle.Save}" oncomplete="handleSubmit(args,'PurchaseOrderCreateDialog11');"/>
<p:commandButton value="#{bundle.Cancel}" onclick="PurchaseOrderCreateDialog11.hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
JSF managed bean
#Named("purchaseOrderController")
#SessionScoped
public class PurchaseOrderController implements Serializable {
public PurchaseOrder prepareCreate() {
System.out.println("Purchase order prepare create");
selected = new PurchaseOrder();
initializeEmbeddableKey();
return selected;
}
}

Datatable link to edit record only works once unless I hit refresh

working with a Primefaces data table and dialog. Each record in data table has a link as such:
<p:commandLink value="#{item.pk}" update=":itemUpdateForm:display"
onclick="PF('itemUpdateDialog').show();" title="Edit">
<f:setPropertyActionListener value="#{item}"
target="#{itemController.selecteditem}" />
</p:commandLink>
The link opens a primefaces dialog successfully the first time but after I submit the form in this popup dialog, which updates that recordset, the links in the datatable will no longer open the dialog again unless I hit refresh on the browser.
Here is the update button in the p:dialog:
<f:facet name="footer">
<p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
oncomplete=" handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
actionListener="#{itemController.doUpdateItem()}" />
<p:commandButton type="reset" value="Reset"></p:commandButton>
</f:facet>
And scopes/pertinent code:
itemController
#ManagedBean
#ViewScoped
public class ItemController implements Serializable {
#PostConstruct
public void init() {
items= itemListProducer.getItems();
}
public void doUpdateItem() {
itemRepository.update(selectedItem);
itemEventSrc.fire(selectedItem);
items = itemListProducer.getitems();
Messages.addAjaxMessage("Update Operation Was Successful!");
}
List Producer
#ApplicationScoped
public class ItemListProducer implements Serializable {
Edit
per comment here is DataTable and the Primefaces update dialog
<h:form id="ItemListForm">
<p:dataTable id="dataTable" var="item"
value="#{itemController.items}"
paginator="true" rows="10"
selection="#{itemController.selectedItems}" rowKey="#{item.oc_id}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
lazy="false" rowsPerPageTemplate="10,15,50">
<f:facet name="header">
Items (#{itemController.items.size()})
</f:facet>
<p:column selectionMode="multiple" style="width:18px"/>
<p:column filterBy="#{item.oc_id}" sortBy="#{item.oc_id}">
<f:facet name="header"><h:outputText value="OC #" /></f:facet>
<p:commandLink value="#{item.pk}" update=":itemUpdateForm:display" onclick="PF('itemUpdateDialog').show();" title="Edit">
<f:setPropertyActionListener value="#{item}" target="#{itemController.selecteditem}" />
</p:commandLink>
</p:column>
more p:columns
<f:facet name="footer">
<p:commandButton value="New item" onclick="PF('dlg1').show();" title="Creates new Item" />
<p:commandButton value="Delete Selected Items"
actionListener="#{itemController.doDeleteItems}"
update="#form, :growl">
<p:confirm header="Confirmation" message="Are you sure you want to remove the selected Items?" />
</p:commandButton>
</f:facet>
</p:dataTable>
<p:confirmDialog global="true">
<p:commandButton value="Yes" type="button"
styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button"
styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:form>
... and dialog
<p:dialog header="Item Update Form" widgetVar="itemUpdateDialog" resizable="false" id="itemDlg">
<h:form id="itemUpdateForm">
<p:panel>
<p:panelGrid id="display" columns="3" cellpadding="4"
style="margin:0 auto;">
<h:outputText value="Title :"></h:outputText>
<p:inputText id="title" value="#{itemController.selectedItem.title}"
required="true"
requiredMessage="Please Enter Title!" />
<p:message for="title" />
other inputs
<f:facet name="footer">
<p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
oncomplete=" handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
actionListener="#{itemController.doUpdateItem()}" />
<p:commandButton type="reset" value="Reset"></p:commandButton>
</f:facet>
</p:panelGrid>
</p:panel>
</h:form>
</p:dialog>
EDIT 2
Thanks to help from Michele's Answer, I determined the issue was related to how I was closing the dialog by its id and not by its widgetVar. I was originally passing in just the id which was used with jQuery effect 'shake', and then closing that object. By adding the widgetVar and using Michele's var d = (typeof dialogWv === "string") ? PF(dialogWv) : dialogWv; I no longer have my issue.
This ultimately works for me:
<p:dialog header="Update Form" widgetVar="itemUpdateDialogWv"
resizable="false" id="itemUpdateDialogId">
<h:form id="itemUpdateForm">
<p:panel>
------content-------
<f:facet name="footer">
<p:commandButton value="Update" update=":ItemListForm:dataTable, :growl"
oncomplete=" handleSubmitRequest(xhr, status, args, 'itemUpdateDialogWv','itemUpdateForm', 'itemUpdateDialogId');"
actionListener="#{itemController.doUpdateItem()}" />
<p:commandButton type="reset" value="Reset"></p:commandButton>
</f:facet>
</p:panelGrid>
</p:panel>
</h:form>
</p:dialog>
function handleSubmitRequest(xhr, status, args, dialogWv, formName, dialogNameId) {
dialog = jQuery('#'+dialogNameId);
var d = (typeof dialogWv === "string") ? PF(dialogWv) : dialogWv;
if(args.validationFailed) {
dialog.effect("shake", { times:5 }, 1000);
} else {
clearForm(formName);
d.hide();
}
}
function clearForm(formName){
jQuery('#'+formName).each(function(){
this.reset();
});
}
Too long for a comment...
You can try:
<p:commandLink value="#{item.pk}" process="#this" update=":itemUpdateForm"
oncomplete="PF('itemUpdateDialog').show();" title="Edit">
<f:setPropertyActionListener value="#{item}" target="#{itemController.selecteditem}" />
</p:commandLink>
specify process="#this": otherwise it defaults to #all and will include the dialog too
use oncomplete instead of onclick
and
<p:commandButton value="Update" process="#form" update="#form, :ItemListForm, :growl"
oncomplete="handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm');"
actionListener="#{itemController.doUpdateItem}" />
specify process="#form": the same as before
add #form to update: generally is a good practice to update the dialog form tho show validation errors and to close dialog only if not validation failed (I don't know how handleSubmitRequest works, maybe it does exactly this)
However:
No js errors on commandButton click?
Is request fired?
If yes, can you post request params for the not working click?
P.S.
handleSubmitRequest(xhr, status, args, 'itemDlg','itemUpdateForm'); has argument itemDlg. Is it correct?
for completeness here is my hideDialog
function hideDialog(dialog, args, status, xhr)
{
var d = (typeof dialog === "string") ? PF(dialog) : dialog;
if(!args.validationFailed)
{
d.hide();
}
}
which is invoked:
<p:commandButton value="Update" process="#form" update="#form :ItemListForm :growl"
oncomplete="hideDialog('itemUpdateDialog', args)"
actionListener="#{itemController.doUpdateItem}" />

primefaces datatable selected row always the same value

I have a datatable with custom delete button when I try to send the id of the selected row to the backing bean, but i always get the same value, this is my code:
<p:dataTable id="result" var="service" value="#{bean.services}" editable="true">
<!-- ajax -->
<p:ajax event="rowEdit" listener="#{bean.onEdit}" update=":form:msg" />
<p:ajax event="rowEditCancel" listener="#{bean.onCancel}" update=":form:msg" />
.....
<p:column headerText="delete" style="width:100px;">
<p:confirmDialog id="confirmation" message="are u sure?" header="delete item" widgetVar="confirmation" showEffect="fade" hideEffect="explode">
<p:commandButton value="Yes" onclick="PF('confirmation').hide()" actionListener="#{bean.onDeleteRow}">
<f:setPropertyActionListener target="#{bean.cve}" value="#{service.id.cve}" />
</p:commandButton>
<p:commandButton value="No" onclick="PF('confirmation').hide()" type="button" />
</p:confirmDialog>
<p:commandLink id="deleteLink" onclick="PF('confirmation').show()" styleClass="ui-icon ui-icon-trash"/>
</p:column>
</p:dataTable>
here is the baking bean code:
#ManagedBean
#ViewScoped
#SuppressWarnings("serial")
public class Bean implements Serializable{
private String cve;
...
public void setcve(String cve) {
this.cve = cve;
}
....
public void onDeleteRow(){
try {
System.out.println("delete-->" + this.cve );
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the tag you can see the value that I'm sending as a parameter but I always leave the last value of datatable ...
What am I doing wrong?
Thank you very much for the support
Also there is another problem in your code, you have and Dialog for each row in the datatable, its a bad idea... you should keep the button on the row and set the entity that you want to delete when click at this button and latter just show the dialog, which is just one... something like this: also, change the propertyAcionListener to your delete link
<p:commandLink id="delete_link" oncomplete="deleteDlg.show();">
Delete
<f:setPropertyActionListener value="#{service.id.cve}" target="#{bean.cve}" />
</p:commandLink>
Where is the selection for datatable?
your xhtml
<p:dataTable id="result" var="service" value="#{bean.services}" editable="true">
must be xhtml
<p:dataTable id="result" var="service" value="#{bean.services}" selection="#{bean.selected}" editable="true">
you can find datatable selection example here

Primefaces Confirm Message Updated Value

I'm trying to show an updated value in confirm dialog message but I keep getting the old value as in this scenario
<h:form>
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<p:commandButton value="SUBMIT" actionListener="#{bean.submit()}">
<p:confirm header="Confirmation" message="Amount is : #{bean.object.amount} ?"/>
</p:commandButton>
<p:confirmDialog global="true">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:panelgGroup/>
</h:form>
Bean code:
#ManagedBean(name="bean")
#ViewScoped
public class Bean implements Serializable {
private SomeClass object;
#PostConstruct
public void init(){
this.object = new SomeClass();
}
public void calculate(){
//do some colculation (not related to amount field in object)
}
public void submit(){
//submit to database
}
//getter setter
}
When I enter a value in amount, lets say 50. and update the cal component I get the updated amount in the outputtext "50". However, in the confirm button message I get amount as 0 instead 50. How can I show the updated value in the confirm message?
PS:
Primefaces-4.0
Take a look at the user guide of primefaces in the confirm dialog section, in the Non-Global mode the document mentioned:
Message facet is
useful if you need to place custom content instead of simple text.
While in the Global mode, I can't find similar sentences like that, and I've tried using the facet in Global mode and it doesn't work.So,
Do you really use this confirm dialog multiple times?
If not:
I suggest you take away the global parameter and change your code like this:
<h:form>
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<p:commandButton value="SUBMIT" actionListener="#{bean.submit()}" oncomplete="PF('confirmDlg').show()"/>
<p:confirmDialog header="Confirmation" widgetVar="confirmDlg">
<f:facet name="message">
<h:outputText value='Amount is : #{bean.object.amount} ?'/>
</f:facet>
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:panelGroup>
</h:form>
.
If so:
(You do use the confirm dialog multiple times and tired of writing several dialogs with same form but different message.)
I suggest you write a dialog on your own,and you can also change the message in the dialog from backing bean like what you did:
<h:form id="myForm">
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<ui:param name="message" value="Amount is :#{bean.object.amount}?" />
<p:commandButton value="SUBMIT" actionListener="#{bean.setMessage(message)}" action="#{bean.submit()}" update="myForm:myDialog" oncomplete="PF('myDlg').show()"/>
</h:panelGroup>
<p:dialog id='myDialog' widgetVar="myDlg" header="Confirmation" modal="true" resizable="false">
<h:panelGrid columns="3">
<h:panelGroup styleClass="ui-icon ui-icon-alert" style="float:right"/>
<h:outputText value="#{bean.message}"/>
<h:outputText/>
<h:outputText/>
<p:commandButton value="Yes" type="button" icon="ui-icon-check" oncomplete="PF('myDlg').hide()"/>
<p:commandButton value="No" type="button" icon="ui-icon-close" onclick="PF('myDlg').hide()"/>
</h:panelGrid>
</p:dialog>
</h:form>
p:confirm does not implement state saving, thus it loses its attributes' values after the first JSF lifecycle. It also evaluates EL only once at view build time.
I posted the solution in this answer.

p:commandLink not working with dataTable

My dataTable is populated by an ajax call, my commandLink (in the datataable) is not pointing to the correct location and always render the same page.and show me in the console :
HtmlLabelRend W Attribute 'for' of label component with id j_id1471051656_3ffdbef6:j_id1471051656_3ffdbfc6 is not defined
But when I put the commandlink outside the datatable the action method works fine.
This problem is rare!, How Can I solve it?
Thanks in advance.
My Jsf Page:
<h:form>
<p:panel header="Busqueda">
<p:panelGrid style="width:100%;">
<p:row>
-----------------------------------(inputs)---------------------------------------
<p:column>
<p:commandButton value="Buscar" update="grilla"
action="#{devolucionAdminController.buscarSD()}">´
</p:commandButton>
</p:column>
</p:row>
</p:panelGrid>
<p:messages closable="true" redisplay="true" id="msj"></p:messages>
</p:panel>
<p:dataTable id="grilla" var="r"
value="#{devolucionAdminController.listado}"
emptyMessage="No se han encontrado solicitudes de devolución">
<p:column headerText="Sec">
<h:outputText value="#{r.idSoliDevo}" />
</p:column>
<p:column headerText="Cuenta">
<h:outputText value="#{r.cuentaId}" />
</p:column>
<p:column headerText="Ver Detalle Sol. Dev ">
<p:commandLink
action="#{bajaController.mostrarSolicitudBaja(r.cuentaId,r.idSoliDevo)}" ajax="false">
<p:commandButton icon="ui-icon-search" title="Ver Detalle" />
</p:commandLink>
</p:column>
</p:dataTable>
<!--works fine -->
<p:commandLink action="#{bajaController.mostrarSolicitudBaja(80003,340)}"
ajax="false">
<p:commandButton icon="ui-icon-search" title="Ver Detalle" />
</p:commandLink>
</h:form>
My first Managed Bean:
#ManagedBean
#RequestScoped
public class DevolucionAdminController {
List<TaSoliDevo> listado;
//getters and setters
........................
public void buscarSD() {
.............................
}
My second Managed Bean:
#ManagedBean
#RequestScoped
public class BajaController {
public String mostrarSolicitudBaja(long cuentaId, long solicDevId) {
.........................
return "goResult";
}}
Use process="#this" and use actionListener instead of action
<p:commandLink process="#this" actionListener="#{bajaController.mostrarSolicitudBaja(80003,340)}"></p:commandLink>
I had the same problem and I was struggling to find a solution but nothing worked for me. Here is how I finally solved the problem :
I removed the ajax attribute
I added process="#this"
Here is what my commandLink looks like after the changes :
<p:commandLink process="#this" action="#{projsSummaryBacking.redirectProjTasks(proj)}" >
<h:outputText value="#{proj.title}" />
</p:commandLink>
I hope that this can help someone. /m\
remove the ajax="false" tag, its work for me
replace your commandLink with
<p:commandButton icon="ui-icon-search" title="Ver Detalle"
action="#{bajaController.mostrarSolicitudBaja(r.cuentaId,r.idSoliDevo)}" ajax="false"/>
Really no need to put a command button inside a command Link, just to put an icon

Resources