JSF: Cancel datatable row edit after data submission in Primefaces - jsf

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()));
}
}
}

Related

Unable to Select Table Rows in PrimeFaces Using RadioButtons

I am trying to develop a web application using a PrimeFaces data table. I am having difficulty getting the object that corresponds to the selected row. Whenever I do that, a null value gets selected. Here is the relevant code:
<p:dataTable id="presTable" var="pres" value="#{presBean.presentations}"
rows="10" scrollable="true" scrollWidth="85%"
selection="#{presBean.selectedPres}" rowKey="#{pres.id}" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,25,100" widgetVar="presTable" filteredValue="#{presBean.filteredPres}" selectionMode="single">
</p:column>
<f:facet name="footer">
<p:commandButton id="updateButton" process="presTable" value="Update" action="#{presBean.printSelectedPres()}"/>
</f:facet>
</p:dataTable>
Java backing bean:
public Presentation getSelectedPres() {
System.out.println("Returning selected presentation: " + selectedPres);
return selectedPres;
}
public void setSelectedPres(Presentation selectedPres) {
System.out.println("Setting selected presentation to " + selectedPres);
this.selectedPres = selectedPres;
}
public void printSelectedPres() {
System.out.println("Printing list of checked presentations:");
System.out.println(selectedPres);
}
Add a column with seletionMode=single
<p:column selectionMode="single" style="width:16px;text-align:center"/>
you can find sample for radio button here : https://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml

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.

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"?

Datatable is not updated after adding records

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;
}

No data load my outputText of Primefaces?

I have a question I have a DataTable, where I have a button in a column edit, capture the Id of the record, and make a list that record to load the data in the object system, peroHola, I have a question I have a DataTable, where I have a button in a column edit, capture the Id of the record, and make a list that record to load the data in the object system, but my text box value is charging.
<p:dataTable id="dataTable" var="sis" value="#{listSistMB.system}"
paginator="true" rows="10" rowIndexVar="rowIndex" selection="#{listSistMB.system}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:column>
<f:facet name="header">
<h:outputText value="Status" />
</f:facet>
<p:selectBooleanButton value="#{sis.stStatus}" onLabel="A" offLabel="I" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Edit" />
</f:facet>
<p:commandButton id="selectEdit" action="#{listSistMB.editSystem}"
icon="ui-icon-search" title="Editar System">
<f:param name="codCode" value="#{sis.cdCode}"/>
</p:commandButton>
</p:column>
</p:dataTable>
In the controller I headed this way the system object.
#Component("listSistMB")
#Scope("view")
public class MantenanceSystemController implements Serializable{
private System system = new System();
public String editSystem(){
try {
String cdCode = (String)FacesContext.getCurrentInstance().getExternalContext().
getRequestParameterMap().get("codCode");
system = confSistemaService.buscarPorId(Long.valueOf(cdCode));
} catch (Exception e) {
e.printStackTrace();
}
return "register-system";
}
It's not charging me the value of the text box.
<p:inputText value="#{listSistMB.system.nbNomCorto}" />
The MantenanceSystemController bean is in #Scope("view")
If the p:dataTable and p:inputText are not on the same view, the information will be lost when changing views.
Consider a different scope (e.g., Conversation) for the bean.

Resources