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" />
Related
I use NetBeans 8.2, GlassFish 5.0, PrimeFaces 5.0.
I created a page with a cell editable data table. When I do the modification on one cell after the ajax event the whole data table replaced by the modified value. Just like the ajax respond does not send back the whole table contents. How can I correct it?
The facelet:
<h:form id="frmDemands">
<p:growl id="msgs" showDetail="true"/>
<div>
<p:dataTable
id="dtblDemands"
value="#{demandUtility.demands}"
var="demand"
editable="true"
editMode="cell"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:ajax event="cellEdit" listener="#{applicantBean.onCellEdit}" update=":frmDemands :frmDemands:msgs"/>
<f:facet name="header">Demands</f:facet>
<p:column headerText="ID">
<h:outputText value="#{demand.id}"/>
</p:column>
<p:column headerText="Amount">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{demand.amount}"/></f:facet>
<f:facet name="input"><p:inputText value="#{demand.amount}"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="State">
<h:outputText value="#{demand.state}"/>
</p:column>
<p:column>
<p:commandButton value="Delete" rendered="#{applicantBean.isDemandDeleteable( demand )}" actionListener="#{applicantBean.onDeleteDemand( demand.id )}" update="#form"/>
</p:column>
</p:dataTable>
</div>
</h:form>
The backing bean handle the cellEdit event:
#Named
#RequestScoped
#Data
public class ApplicantBean
{
#Inject
private DemandUtility demandUtility;
...
public void onCellEdit( CellEditEvent event_ )
{
int rowIndex = event_.getRowIndex();
double newValue = (Double) event_.getNewValue();
Demand demand = demandUtility.getDemands().get( rowIndex );
demand.setAmount( newValue );
Event event = new Event( demandUtility.getNextEventId(), new Date(), "Demand (" + demand.getId() + ") modified! New amount: " + newValue );
demandUtility.getEvents().add( event );
}
...
}
When I try to set the #parent value to the update attribute of the ajax event the dataTable disappears as well.
Can somebody help me, please?
Create a which updates you table and change your Scope to #ViewScoped
It worked for me.
<h:form id="frmDemands">
<p:growl id="msgs" showDetail="true"/>
<p:remoteCommand name="rcCellEditUpdate"
update=":frmDemands:dtblDemands :frmDemands:msgs" />
<div>
<p:dataTable
id="dtblDemands"
value="#{demandUtility.demands}"
var="demand"
editable="true"
editMode="cell"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:ajax event="cellEdit" listener="#{applicantBean.onCellEdit}" oncomplete="rcCellEditUpdate();"/>
<f:facet name="header">Demands</f:facet>
<p:column headerText="ID">
<h:outputText value="#{demand.id}"/>
</p:column>
<p:column headerText="Amount">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{demand.amount}"/></f:facet>
<f:facet name="input"><p:inputText value="#{demand.amount}"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="State">
<h:outputText value="#{demand.state}"/>
</p:column>
<p:column>
<p:commandButton value="Delete" rendered="#{applicantBean.isDemandDeleteable( demand )}" actionListener="#{applicantBean.onDeleteDemand( demand.id )}" update="#form"/>
</p:column>
</p:dataTable>
</div>
</h:form>
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.
This question already has answers here:
How to choose the right bean scope?
(2 answers)
Closed 7 years ago.
So, I am loading a list from H2 database to be shown, and it is updated with data from form on previous page. The datatable is update only once in session, after I submit form first time. If I reset tomcat server, all the data submitted in last session will be shown. I will upload all the code that I consider relevant,:
Managed bean, with the TaskList datatable:
#ManagedBean
#SessionScoped
public class TaskListController {
private List<Task> taskList;
private Task task;
#PostConstruct
private void init() {
taskList = TaskServiceDatabase.taskList();
}
public String loadFirstPage() {
return "createNewTask.xhtml";
}
public List<Task> getTaskList() {
return taskList;
}
//getters and setters
Tasklist method:
public static List<Task> taskList() {
List<Task> taskList = new ArrayList<Task>();
try {
taskList = DatabaseUtils.fetchTask();
} catch (Exception e) {
e.printStackTrace();
}
return taskList;
}
Fetch task method is communicating with database, I am fairly certain this works properly, if it is needed, I can add it.
And here is the.xhtml file:
<h:form id="form">
<p:dataTable id="taskTable" var="task" rowIndexVar="taskNumber"
value="#{taskListController.taskList}" paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:column>
<f:facet name="header">
<h:outputText value="Surname" />
</f:facet>
<h:outputText value="#{task.user.surname}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{task.user.name}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Username" />
</f:facet>
<h:outputText value="#{task.user.username}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Project name" />
</f:facet>
<h:outputText value="#{task.project.projectName}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Company name" />
</f:facet>
<h:outputText value="#{task.project.companyName}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Task description" />
</f:facet>
<h:outputText value="#{task.description}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Time (h)" />
</f:facet>
<h:outputText value="#{task.time}" />
</p:column>
</p:dataTable>
<h:commandButton action="#{taskListController.loadFirstPage}"
value="Return" update="form" />
</h:form>
So, what did I do wrong?
Changing scope of bean to ViewScoped solved the issue
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"?
I Want to get selectOneMenu value in bean but value is not getting correctly.SubstituteHoliday is a boolean variable.But,I getting false only for both yes and no selectItems.How could i get appropriate value for selectOneMenu.Based on that selectOneMenu value if yes means i want to diabled substitue date cell...
Thanks in advance...
<p:dataTable id="manager" var="item" value="#{employeeWorkingHolidayBean.userListTwo}"
paginator="true" rows="10"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="2,5,10,15"
editable="true" editMode="cell" style="width:600px;" styleClass="postformatte"
emptyMessage="No Employee Working Holiday Details found with given criteria" resizableColumns="true" >
<p:ajax event="cellEdit" listener="#{employeeWorkingHolidayBean.onCellEdit}"
update=":form:growl"/>
<p:ajax event="colResize" update=":form:growl" listener="#{employeeWorkingHolidayBean.onResize}" />
<p:column headerText="Employee Id" width="90" >
<h:outputText value="#{item.employeeId}" />
</p:column>
<p:column headerText="Is Substitute Holiday">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{item.substituteHoliday}" /></f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{item.substituteHoliday}" style="width:100%">
<f:selectItems value="#{employeeWorkingHolidayBean.subsholiday}"/>
<p:ajax event="change" update="subdate"/>
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Substitute Date" >
<p:cellEditor>
<f:facet name="output"><p:calendar pattern="dd-MM-yyyy" yearRange="#{c-100}" navigator="true" showButtonPanel="true" value="#{item.substituteDate}"/></f:facet>
<f:facet name="input"><p:calendar id="subdate" pattern="dd-MM-yyyy" yearRange="#{c-100}" navigator="true" showButtonPanel="true" value="#{item.substituteDate}" style="width:55px;" disabled="#{employeeWorkingHolidayBean.isdiableEffectdate}"/></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
Bean:
private Boolean isdiableEffectdate;
public Boolean getIsdiableEffectdate() {
return isdiableEffectdate;
}
public void setIsdiableEffectdate(Boolean isdiableEffectdate) {
this.isdiableEffectdate = isdiableEffectdate;
}
public void onCellEdit(CellEditEvent event)
{
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
logger.info("Old value"+oldValue);
logger.info("New value"+newValue);
if(newValue.equals(true))
{
logger.info("enter if true");
isdiableEffectdate=true;
}
else
{
logger.info("enter if false");
isdiableEffectdate=false;
}
if(newValue != null && !newValue.equals(oldValue))
{
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
Add a VCE (Value changeListener Event) for your select as,
<h:selectOneMenu value="#{item.substituteHoliday}"
valueChangeListener="#{item.selectHolidayValueChangeListner}"
style="width:100%">
<f:selectItems value="#{employeeWorkingHolidayBean.subsholiday}"/>
<p:ajax event="change" update="subdate"/>
</h:selectOneMenu>
And in your valueChangeListener method assign new value to global variable as,
public void selectHolidayValueChangeListner(ValueChangeEvent vce) {
if (vce.getNewValue() != null) {
substituteHoliday = vce.getNewValue().toString();
}
}
Now, in your ajax method get the value of substituteHoliday and do whatever is required.