Datatable is not updated after adding records - jsf

I have an init() function that returns a list of emails that will be displayed in a Primefaces datatable. And I have a commandButton that extract emails and persist them in the dataTable. These new records show up in the dataTable only if I log out and log in.
This is my init() function ( my managed Bean is annotated with #ManagedBean(name = "mailMB") and #SessionScoped) :
#PostConstruct
public void init() {
emails = new ArrayList();
idCustomer = (String) session.getAttribute("idCustomer");
System.out.println(idCustomer + " this is it");
cust = customerBusinessLocal.findById(idCustomer);
System.out.println(cust.getName());
datas = dataBusinessLocal.findByCustomer(cust);
System.out.println(datas.size());
for (Data d : datas) {
for (Email e : mailBusinessLocal.mailsByData(d)) {
emails.add(e);
}
}
public List<Email> getEmails() {
return emails;
}
In my page xhtml i've implemented the code below:
<h:form id="form">
<p:commandButton value="Extract" update="tableemails" id="ajax" widgetVar="extractButton"
action="#{mailMB.searchEmails()}"
icon="ui-icon-disk" styleClass="ui-priority-primary"
onstart="blockUIWidget1.block()"
oncomplete="blockUIWidget1.unblock()"/>
<pe:blockUI target="formulaire" widgetVar="blockUIWidget1">
<h:panelGrid columns="2">
<img src="../../pictures/animated-loading-bar.gif" width="264" height="34" alt="animated-loading-bar"/>
<h:outputText value="Please wait..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
<p:panel id="display" header="Emails" >
<p:dataTable id="tableemails" value="#{mailMB.emails}" var="item" rowsPerPageTemplate="5,10,15" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
paginator="true" rows="10" styleClass="case-table" emptyMessage="No records found with given criteria" paginatorPosition="bottom"
filteredValue="#{mailMB.filteredMails}" rowKey="#{item.id}"
selection="#{mailMB.selectedMail}" selectionMode="single" >
<p:ajax event="rowSelect" update=":form:display"/>
<p:column styleClass="blockable" filterStyle="width: 250px" filterBy="#{item.email} " sortBy="#{item.email}">
<f:facet name="header">
<h:outputText value="Email"/>
</f:facet>
<h:outputText value="#{item.email}"/>
</p:column>
</p:dataTable>
</p:panel>
</h:form>

it looks like you do not reload your List<Email> emails after persisting some new data. #PostConstract is executed once after your bean is created (sincce it's #SessionScoped it's created once per session), thats why you see changes only after another login. Add a method repopulateEmails() that would load data from database and run it after you add/remove something, just add it to your persist() method.
public void persist()
{
....
getEntityManager().persist(getInstance());
getEntityManager().flush();
emails = null;
......
}
public List<Email> getEmails(){
if(emails == null){
emails = repopulateEmails();
}
return emails;
}

Related

Primefaces dataTable with multiple row count

the next datatable is a report of files transferred and not transferred by each period (month / year). I need to include multiple row counts in the currentPageReportTemplate attribute. The total count, the count of transferred files and the count of not transferred files.
<p:dataTable id="repFiles" var="rep" value="#{reportFilesBean.list}" filteredValue="#{reportFilesBean.listFiltered}"
paginator="true" rows="20" sortMode="multiple" emptyMessage="Empty result"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
currentPageReportTemplate="Total: {totalRecords} / Transferred: #{reportFilesBean.countTrans} / Not transferred: #{reportFilesBean.countNotTrans}"
rowsPerPageTemplate="10,20,30,40,50,100" scrollable="true" style="width: 100%;" >
<f:event type="org.primefaces.event.data.PostFilterEvent" listener="#{reportFilesBean.postFilter}" />
<f:facet name="header">
Files transfered
</f:facet>
<p:column sortBy="#{rep.period}" filterBy="#{rep.period}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Period" />
</f:facet>
<h:outputText value="#{rep.period}" />
</p:column>
<p:column sortBy="#{rep.filename}" filterBy="#{rep.filename}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Filename" />
</f:facet>
<h:outputText value="#{rep.filename}" />
</p:column>
<p:column sortBy="#{rep.date}" filterBy="#{rep.date}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Date" />
</f:facet>
<h:outputText value="#{rep.date}" />
</p:column>
</p:dataTable>
#ManagedBean
#ViewScoped
public class ReportFilesBean implements Serializable {
private List<ReportFile> list;
private List<ReportFile> listFiltered;
private Long countTrans;
private Long countNotTrans;
public ReportFilesBean() {
list = new ArrayList<ReportFile>();
countTrans = 0L;
countNotTrans = 0L;
}
public void generateReport(ActionEvent actionEvent) {
Long[] c = {0L, 0L};
list = dao.reportFile(c);
countTrans = c[0];
countNotTrans = c[1];
}
public void postFilter(ComponentSystemEvent e) {
countTrans = 0L;
countNotTrans = 0L;
for (ReportFile r : listFiltered) {
if (r.getFilename() != null){
cantTrans++;
} else {
cantNoTrans++;
}
}
}
/* Getters and Setters */
}
At generate the report the variables countTrans and countNotTrans are displayed correctly. However at the time of filtering they maintain the value initially loaded. I debug the postFilter method and the count is successful but the datatable is not updated.
Please your help, I have read and I find no example with a similar scenario.
Thanks in advance.

JSF: Cancel datatable row edit after data submission in Primefaces

I'm developing a web-app in JSF 2.1 + Primefaces 5.1. I have a datatable with editable rows. I catch the rowEdit event and call a DB procedure to do some validations of the new data and update the record when the user clicks the "check" button. But there's a problem: the datatable row in the GUI is updated whether the validations succeed or fail. I want the changes in the row data to be reversed to their previous state if the validations done in the DB procedure fail. How can I do that?
<p:dataTable id="users_table_id" var="user" value="#{usersBean.users}" rowKey="#{user.id}" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" emptyMessage="#{msgs.no_records}" sortBy="#{user.id}" sortOrder="ascending" rows="15" editable="true">
<f:facet name="header">
#{msgs.users}
</f:facet>
<p:ajax event="rowEdit" listener="#{usersBean.onRowEdit}"/>
<p:ajax event="rowEditInit" listener="#{usersBean.onRowEditInit}"/>
<p:column headerText="#{msgs.id}" sortBy="#{user.id}" styleClass="centered-column">
#{user.id}
</p:column>
<p:column headerText="#{msgs.description}" sortBy="#{user.description}" styleClass="centered-column">
<p:cellEditor>
<f:facet name="output">#{user.description}</f:facet>
<f:facet name="input"><p:inputText value="#{user.description}" styleClass="editable-cell"/></f:facet>
</p:cellEditor>
</p:column>
...
<p:column styleClass="datatable-row-editor">
<p:rowEditor/>
</p:column>
</p:dataTable>
#ManagedBean
#ViewScoped
public class UsersBean implements Serializable {
private List<DtoUser> users;
public void onRowEdit(RowEditEvent event) {
logger.entry();
DtoUser dtoUser = (DtoUser)event.getObject();
this.updateUser(dtoUser);
logger.exit();
}
public void updateUser(DtoUser dtoUser) {
try {
logger.entry(dtoUser);
DtoBoUsers dtoBoUsers = dtoUser.toDtoBoUsers();
DtoTypeGenericResponse genericResponse = usersService.updateUser(dtoBoUsers);
if (genericResponse.isError()) {
// error in user update
} else {
// update successful
}
logger.exit(dtoUser);
} catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e.fillInStackTrace()));
}
}
}

Primefaces JSF RowEditCancel event duplicates a row deleted from a datatabale

I have two primefaces datatable A and B, the goal is to add an item from A to B, so I have two ArrayList for each datatable.
Each datatable has <p:ajax event="rowEditCancel" listener="#{item.onCancel}" update=":datatableA :datatableB" />
the listener is fired and the object is deleted in the datatable A and added to the datatable B but the item that remains in the datatable A is duplicated, but when I clicked in that item it throws a NoRowAvailableException
Here is the form
<h:form id="formulario">
<p:accordionPanel id="ap1">
<p:tab title="Examen">
<h:panelGrid columns="2" cellpadding="10">
</h:panelGrid>
</p:tab>
<p:tab title="Preguntas disponibles" id="tb2">
<h:panelGroup id="pg2">
<p:dataTable id="dtDisponibles" value="#{examenPregunta.itemsDisponibles}" var="pregunta"
rows="10" paginator="true"
editable="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" lazy="true" >
<f:facet name="header">
<h:outputText value="Preguntas disponibles"/>
</f:facet>
<!--" <p:ajax event="rowEditCancel" listener="#{examenPregunta.agregarItem}" update="#form" />-->
<p:ajax event="rowEditCancel" listener="#{examenPregunta.agregarItem}" update=":formulario:ap1:dtSeleccionados :formulario:ap1:dtDisponibles />
<p:column headerText="Clave" >
<h:outputText value="#{pregunta.identificador}"/>
</p:column>
<p:column headerText="Enunciado">
<h:outputText escape="false" value="#{pregunta.enunciado}"/>
</p:column>
<p:column>
<p:rowEditor />
</p:column>
</p:dataTable>
</h:panelGroup>
</p:tab>
<p:tab title="Preguntas seleccionadas" id="tab3">
<h:panelGroup id="pg3">
<p:dataTable id="dtSeleccionados" value="#{examenPregunta.itemsSeleccionados}"
editable="true"
var="pregunta" rows="10" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" lazy="true" >
<f:facet name="header">
<h:outputText value="Preguntas seleccionadas"/>
</f:facet>
<!--<p:ajax event="rowEditCancel" listener="#{examenPregunta.quitarItem}" update="#form" /> -->
<p:ajax event="rowEditCancel" listener="#{examenPregunta.quitarItem}" update=":formulario:ap1:dtDisponibles :formulario:ap1:dtSeleccionados" />
<p:column headerText="Clave" >
<h:outputText value="#{pregunta.identificador}"/>
</p:column>
<p:column headerText="Enunciado">
<h:outputText escape="false" value="#{pregunta.enunciado}"/>
</p:column>
<p:column>
<p:rowEditor />
</p:column>
</p:dataTable>
</h:panelGroup>
</p:tab>
</p:accordionPanel>
</h:form>
and here is the managed bean
#ManagedBean
#SessionScoped
public class ExamenPregunta implements Serializable {
private static final long serialVersionUID = 1L;
private Date currentDate = new Date();
private String idExamen = "";
private ITOAssessmentTest examen = null;
ITOAssessmentItem pregunta = new ITOAssessmentItem();
ITOAssessmentItem[] arrPregunta = null;
private ArrayList<ITOAssessmentItem> itemsDisponibles = new ArrayList<ITOAssessmentItem>();
private ArrayList<ITOAssessmentItem> itemsSeleccionados = new ArrayList<ITOAssessmentItem>();
public void agregarItem(RowEditEvent event){
System.out.println("agregarItem");
itemsDisponibles.remove((ITOAssessmentItem) event.getObject());
itemsSeleccionados.add((ITOAssessmentItem) event.getObject());
}
public void quitarItem(RowEditEvent event){
System.out.println("quitarItem");
itemsDisponibles.add((ITOAssessmentItem) event.getObject());
itemsSeleccionados.remove((ITOAssessmentItem) event.getObject());
}
/**
* #return the itemsDisponibles
*/
public ArrayList<ITOAssessmentItem> getItemsDisponibles() {
return itemsDisponibles;
}
/**
* #return the itemsSeleccionados
*/
public ArrayList<ITOAssessmentItem> getItemsSeleccionados() {
return itemsSeleccionados;
}
}
Thanks in advance!!!
you code looks ok.
maybe its an bug for this combination accordionPanel->datatable->ajax->rowEdit.
with
<p:column>
<p:commandButton value="foo" action="#{examenPregunta.doAction(pregunta)}"
process="#this"
update=":formulario:dtDisponibles :formulario:dtSeleccionados"></p:commandButton>
</p:column>
its work for me.
why did u have a lazy="true"?

How to put a delete button for an object in a Primefaces data table?

I have a data table with a couple of rows and I have a column where I have a form with a simple button that deletes the object in that row.
So first the working version:
<h:dataTable value="#{actorTableBackingBean.allActors}"
var="actor" styleClass="table table-bordered">
<h:column headerText="Actor Name" sortBy="#{actor.firstName}">
<h:outputText value="#{actor.firstName}"/>
</h:column>
<h:column headerText="Actor Detail">
<h:form>
<h:commandButton value="Delete Actor"
styleClass="btn btn-primary"
action="#{actorTableBackingBean.deleteActor(actor.actorId)}"/>
</h:form>
</h:column>
</h:dataTable>
And this is what deleteActor method looks like:
public String deleteActor(String id){
removeActorWithId(id);
return "/allActors.xhtml";
}
private void removeActorWithId(String id){
int idk = Integer.parseInt(id);
for(Actor a:allActors){
if(a.getActorId() == idk){
allActors.remove(a);
return;
}
}
}
So this exactly works as expected as it is.
However, when I use a Pagination Data table of Primefaces as shown in here, delete button works only for the FIRST ROW in the second case and only for the first time.
When I click on button "Delete" for other rows, simply nothing happens.
What might be the reason?
For second situation just put the < form > tags around p:dataTable as seen in the link and replace everything like h:dataTable to p:dataTable and p:column etc...
I would suggest that you make the form tag contain your datatable.
This works:
<h:form id="actorsTableForm">
<p:dataTable id="actorsTable" var="item"
value="#{actorsMB.actorList}" selectionMode="single"
rowKey="#{item.description}" paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" paginatorPosition="bottom">
<p:column headerText="Actor Id" >
<h:outputText value="#{item.id}" />
</p:column>
<p:column headerText="Actor Description">
<h:outputText value="#{item.description}" />
</p:column>
<p:column>
<p:commandButton icon="ui-icon-trash"
title="Delete this actor"
actionListener="#{actorsMB.remove(item)}"
ajax="false" />
</p:column>
</p:dataTable>
</h:form>
And the method in the managed bean:
public void remove(Actor actor) {
try {
actorService.remove(actor);
actorList = actorService.searchAll();
} catch (Exception e) {
e.printStackTrace();
}
}
Hope it helps.
Following code might help you.
Your xhtml code should be like this
<h:form>
<h:dataTable value="#{actorTableBackingBean.allActors}"
binding="#{actorTableBackingBean.dataTable}"
var="actor" styleClass="table table-bordered">
<h:column headerText="Actor Name" sortBy="#{actor.firstName}">
<h:outputText value="#{actor.firstName}"/>
</h:column>
<h:column headerText="Actor Detail">
<h:commandButton value="Delete Actor"
styleClass="btn btn-primary"
action="#{actorTableBackingBean.deleteActor}"/>
</h:column>
</h:dataTable>
</h:form>
You have to add one DataTable variable in bean file
private javax.faces.component.html.HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
Your delete method should be like this
public String deleteActor(){
Actor model = (Actor) dataTable.getRowData();
removeActorWithId(model);
return "/allActors.xhtml";
}
private void removeActorWithId(Actor model){
if(model!=null){
allActors.remove(model);
}
}

Event:cellEdit is not supported primefaces datatable cell edit

i am trying to implement a primefaces data table with cell editing. Something similar to the one implemented here:
http://www.primefaces.org/showcase/ui/datatableCellEditing.jsf
So here is my jsf datatable code:
<h:form>
<p:growl id="messages" showDetail="true"/>
<p:panel id="dataPanel">
<p:dataTable
id="imagesDataTable"
var="cRImageData"
value="#{syncCenterBean.cRImageDataList}"
widgetVar="imagesTable"
paginator="true"
sortMode="multiple"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,15,20,30"
paginatorAlwaysVisible="false"
editable="true"
editMode="cell">
<p:ajax event="cellEdit" listener="#{syncCenterBean.onCellEdit}" update=":form:messages" />
<p:column sortBy="#{cRImageData.imId}" headerText="ID" style="width:100px;text-align:center;">
<h:outputText value="#{cRImageData.imId}" />
</p:column>
<p:column headerText="Image Name" style="width:180px;text-align:center;">
<h:outputText value="#{cRImageData.imName}" />
</p:column>
<p:column headerText="Image Type" style="width:170px;text-align:center;">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{cRImageData.imType}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{syncCenterBean.cRImageTypeList}" style="width:100%">
<f:selectItems value="#{syncCenterBean.cRImageTypeList}" var="imTypeId" itemLabel="#{imTypeId}" itemValue="#{imTypeId}" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
...
And here is the code for my back bean:
#ManagedBean(name = "syncCenterBean")
#RequestScoped
public class SyncCenterBean implements Serializable {
....
List<CRImageData> cRImageDataList;
List<CRImageType> cRImageTypeList;
#SuppressWarnings("unchecked")
public SyncCenterBean(){
cRImageTypeList = getImageTypesDB(); //returns a populated list of objects
cRImageDataList = getImageDataDB(); //returns a populated list of objects
}
...
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
But when i try to load the view i get:
Caused by: javax.faces.view.facelets.TagException: .... Event:cellEdit is not supported.
on line:
<p:ajax event="cellEdit" listener="#{syncCenterBean.onCellEdit}" update=":form:messages" />
You should make your datatable editable for this event
<p:datatable editable="true" editMode="cell" />

Resources