How to update and show number of records in p:dataTable after filter? - primefaces

After filtering of primefaces 'tasksDataTable', the 'number of records' does not update.
For example before filtering number of records is 45, and by filtering table i get 3 records as result. But 'number of records' is already 45 (i expect to show 3 for 'number of records' after filtering).
How can i handle it?
<p:dataTable var="recordEntity"
id="rulesDataTable"
widgetVar="rulesDataTable"
value="#{bossCartable.tasksDataTable}"
paginator="true"
paginatorAlwaysVisible="false"
rows="#{paginationModel.rows}"
paginatorTemplate="#{paginationModel.paginationTemplate}"
rowsPerPageTemplate="#{paginationModel.rowsPerPageTemplate}"
currentPageReportTemplate="#{paginationModel.currentPageReportTemplate}"
selectionMode="single"
selection="#{bossCartable.selectedRuleRow}"
rowIndexVar="rowIndex"
sortBy="#{recordEntity.id}"
emptyMessage="No record found!"
rowKey="#{recordEntity.id}"
resizableColumns="true"
>
<f:facet name="header">
<div class="row align-content-center">
Tasks
<h:outputLabel value="number of records: #{bossCartable.tasksDataTable.size()}"/>
</div>
</f:facet>
<p:column headerText="id" width="5%" filterMatchMode="contains"
filterBy="#{recordEntity.id}" sortBy="#{recordEntity.id}" sortable="true">
<h:outputText value="#{recordEntity.id}"/>
</p:column>
<p:column headerText="description" filterMatchMode="contains"
filterBy="#{recordEntity.description}">
<h:outputText value="#{recordEntity.description}"/>
</p:column>
<p:column headerText="startDate" width="8%" filterMatchMode="contains"
filterBy="#{recordEntity.startDate}">
<h:outputText value="#{recordEntity.startDate}"/>
</p:column>
<p:column headerText="endDate" width="8%" filterMatchMode="contains"
filterBy="#{recordEntity.endDate}">
<h:outputText value="#{recordEntity.endDate}"/>
</p:column>
</p:dataTable>

With non lazy loading the filtered value can be stored using the filteredValue attribute. See: https://primefaces.github.io/primefaces/8_0/#/components/datatable
This will allow you to use:
<p:dataTable value="#{bossCartable.tasksDataTable}"
filteredValue="#{bossCartable.tasksFiltered}"
...>
</p:dataTable>
and
#{bossCartable.tasksFiltered.size()}
where tasksFiltered should point to a writable List.
Also, your header facet will not be updated by magic, you should put you text in a component and update that component on the filter event of the data table.
See also:
Primefaces datatable update in f:facet name="header" not working
https://primefaces.github.io/primefaces/8_0/#/components/datatable?id=ajax-behavior-events

Related

org.primefaces.model.SelectableDataModel when selection is enabled

I have this problem, and I don't understand why...I used it all the time in this way
<p:dataTable id="datatable" var="ligne" value="#{ficheMB.lignes}"
selection="#{ficheMB.selectedLignes}" rowKey="#{ligne.id}" >
<p:column selectionMode="multiple" style="width:16px;text-align:center"/>
<p:column headerText="Article">
<h:outputText value="#{ligne.article.nom}" />
</p:column>
<p:column headerText="Tarif">
<h:outputText value="#{ligne.article.tarif}" />
</p:column>
this is the error
javax.faces.FacesException: DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.
at org.primefaces.component.datatable.DataTable.getRowKeyFromModel(DataTable.java:1409)
at org.primefaces.component.datatable.DataTableRenderer.encodeRow(DataTableRenderer.java:1244)
at org.primefaces.component.datatable.DataTableRenderer.encodeRows(DataTableRenderer.java:1184)
thank you for your help

p:dataTable doesn't display each p:selectManyCheckbox selected

Passed on the demo example of:
https://www.primefaces.org/showcase/ui/data/datatable/basic.xhtml
and I can show the complete example as primefaces-test-master and run as mvn clean jetty:run-exploded
I've created a displays using 'p:selectManyCheckbox ' to show all my Year, Brand, Colour, Price & Sold' as:
<p:selectManyCheckbox id="carColumns" value="#{carService.selectedItems}">
<f:selectItem itemLabel="Year" itemValue="Year"/>
<f:selectItem itemLabel="Brand" itemValue="Brand"/>
<f:selectItem itemLabel="Colour" itemValue="Colour"/>
<f:selectItem itemLabel="Price" itemValue="Price"/>
<f:selectItem itemLabel="Sold" itemValue="Sold"/>
<p:ajax listener="#{carService.selectedItemsChanged}" update="formCars:tblCars"/>
</p:selectManyCheckbox>
It then displays the p:dataTable and each p:column of the 'car' plus the others:
<p:dataTable id="tblCars" var="car" value="#{dtBasicView.cars}" paginator="true"
rows="100"
multiViewState="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100"
resizableColumns="true"
draggableColumns="true"
scrollWidth="100%">
<f:facet name="header">
<p:commandButton id="columnTogglerCars" type="button" value="Columns" style="float:right"
icon="pi pi-align-justify"/>
<p:columnToggler datasource="tblCars" trigger="columnTogglerCars"/>
</f:facet>
<p:column headerText="Id" rendered="true">
<h:outputText value="#{car.id}"/>
</p:column>
<p:column headerText="Year" sortBy="#{car.year}" rendered="#{carService.yearColumnRendered}">
<h:outputText value="#{car.year}"/>
</p:column>
<p:column headerText="Brand" sortBy="#{car.brand}" rendered="#{carService.brandColumnRendered}">
<h:outputText value="#{car.brand}"/>
</p:column>
<p:column headerText="Colour" sortBy="#{car.colour}" rendered="#{carService.colourColumnRendered}">
<h:outputText value="#{car.colour}"/>
</p:column>
<p:column headerText="Price" sortBy="#{car.price}" rendered="#{carService.priceColumnRendered}">
<h:outputText value="#{car.price}"/>
</p:column>
<p:column headerText="Sold" sortBy="#{car.sold}" rendered="#{carService.soldColumnRendered}">
<h:outputText value="#{car.sold}"/>
</p:column>
</p:dataTable>
If I then alter the orders (up or down) displayed of p:column headerText on the selected items of p:selectManyCheckbox then sometimes will not actually displayed each of the 'Year, Brand, Colour, Price & Sold' in dataTable.
Am I doing something wrong with p:selectManyCheckbox and p:dataTable ?
(1) Hows all five images 'Year, Brand, Colour, Price & Sold'.
(2) Show two pages 'Year, Brand'
(3) Selects "Year, Brand, Colour but it only shows '"Year, Brand', though selected (Colour)!
See the code at: https://www.dropbox.com/s/vfugj0fppejtti7/primefaces-test-master.zip?dl=0
I had the same problem with ajax and p:dataTable, I solve it insert the p:dataTable inside the p:panel and with ajax I have update the panel, an example
<p:panel id="panel-update">
<p:dataTable id="tblCars" var="car" value="#{dtBasicView.cars}" paginator="true"
rows="100"
multiViewState="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100"
resizableColumns="true"
draggableColumns="true"
scrollWidth="100%">
<f:facet name="header">
<p:commandButton id="columnTogglerCars" type="button" value="Columns" style="float:right"
icon="pi pi-align-justify"/>
<p:columnToggler datasource="tblCars" trigger="columnTogglerCars"/>
</f:facet>
<p:column headerText="Id" rendered="true">
<h:outputText value="#{car.id}"/>
</p:column>
<p:column headerText="Year" sortBy="#{car.year}" rendered="#{carService.yearColumnRendered}">
<h:outputText value="#{car.year}"/>
</p:column>
<p:column headerText="Brand" sortBy="#{car.brand}" rendered="#{carService.brandColumnRendered}">
<h:outputText value="#{car.brand}"/>
</p:column>
<p:column headerText="Colour" sortBy="#{car.colour}" rendered="#{carService.colourColumnRendered}">
<h:outputText value="#{car.colour}"/>
</p:column>
<p:column headerText="Price" sortBy="#{car.price}" rendered="#{carService.priceColumnRendered}">
<h:outputText value="#{car.price}"/>
</p:column>
<p:column headerText="Sold" sortBy="#{car.sold}" rendered="#{carService.soldColumnRendered}">
<h:outputText value="#{car.sold}"/>
</p:column>
</p:dataTable>
</p:panel>
Now with ajax can update the panel
<p:selectManyCheckbox id="carColumns" value="#{carService.selectedItems}">
<f:selectItem itemLabel="Year" itemValue="Year"/>
<f:selectItem itemLabel="Brand" itemValue="Brand"/>
<f:selectItem itemLabel="Colour" itemValue="Colour"/>
<f:selectItem itemLabel="Price" itemValue="Price"/>
<f:selectItem itemLabel="Sold" itemValue="Sold"/>
<p:ajax listener="#{carService.selectedItemsChanged}" update="formCars:panel-update"/>
</p:selectManyCheckbox>
you're doing something that's not consistent, the p:columnToggler uses javascript to show and hide those dataTable columns, but using your selectManyCheckbox you're using the jsf some managed bean to not render some column, first of all stick to one of those, as the selectManyCheckbox and it's managed bean carService.selectedItems have no idea what you have hidden or displayed using the p:columnToggler.
anyway if you're trying to create a p:dataTable that has dynamic columns then you should do it as in this example.
Edit 1:
As described in Kukeltje comment, using visible attribute of p:column is the way to go instead of using rendered if you really nead to manage showing and hiding columns in the backing bean and still be able to use the columnToggler

Datatable emptyMessage is not shown in PF5.3

I am using PF 5.3, on (weblogic 11g/jsf2.0/java 1.6).
I thought the issue of not shown emptyMessage in Datatable is fixed in 5.3, but inspite of using the latest version, i still dont see the message. Below is my sample code.
<p:dataTable id="attaDt" var="fileRow" value="#{pendpaybean.selectedPayDetailsFiles}"
rowIndexVar="rowIndex"
emptyMessage="No Files Uploaded"
>
<p:column headerText="Uploaded Date"
width="15px;" style="text-align:center"
>
<h:outputText value="#{fileRow.columns[0]}" />
</p:column>
<p:column headerText="Uploaded By"
width="30px;" style="text-align:center"
>
<h:outputText value="#{fileRow.columns[3]}" />
</p:column>
</p:datatable>
Any help ?
Your code works well. NOTE I put attribute value to null for showing emptyMessage.
Your adapted code:
<h:body>
<h:form>
<p:dataTable id="attaDt" value="#{null}" var="fileRow" rowIndexVar="rowIndex" emptyMessage="No Files Uploaded">
<p:column headerText="Uploaded Date" width="15px;" style="text-align:center">
<h:outputText value="#{fileRow.columns[0]}" />
</p:column>
<p:column headerText="Uploaded By" width="30px;" style="text-align:center">
<h:outputText value="#{fileRow.columns[3]}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>

Can I use primefaces DataTables to display a matrix of data?

Basically, I have 2 collections of objects: List and List. Each person has a value in each criteria, which builds the matrix to be displayed:
criteria1 criteria2 criteria3 ...
person1 2 5 8
person2 4 3 1
person3 6 9 0
...
The number of elements in each collection is unknown since they are coming from query results. My model has 3 tables: criteria, person and criteria_person (which has the personId, criteriaId and qualification).
I have been able to display the datatable with these collections but I have no clue about how to relate them to the qualification associated to them, and then make them persist. So, any guidance would be much appreciated.
You just asked such a wide question. For this you can use row expansion see more
You can simple add a table with person name and criteria would be it's inner table like in the example on the showcase.
here is sample example:
<p:dataTable var="person" value="#{dtBasicView.peronsViewList}">
<f:facet name="header">
Person with criteria
</f:facet>
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column headerText="Person Name">
<h:outputText value="#{person.personName}" />
</p:column>
<p:column headerText="Reg. Date">
<h:outputText value="#{person.regDate}" />
</p:column>
<p:rowExpansion>
<p:panelGrid columns="2" columnClasses="label,value" style="width:300px">
<p:dataTable var="cri" value="#{person.criteria}">
<p:column headerText="Id">
<h:outputText value="#{cri.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{cri.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{cri.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{cri.color}" />
</p:column>
</p:dataTable>
</p:panelGrid>
</p:rowExpansion>
</p:dataTable>
I am not sure if I understood the question 100%, but I solved something similar with p:columns and a backing bean method which resolves the value for the current cell:
<p:dataTable value="#{curSearch.getSearchResults()}" var="curSearchResult">
<p:columns value="#{curSearch.determineItems()}" var="curSearchItem">
<f:facet name="header">
<h:outputText value="#{curSearchItem}" />
</f:facet>
<h:outputText value="#{someUiBusinessLogicBean.generatePropertyValue(curSearchResult, curSearchItem)}" />
</p:columns>
</p:dataTable>
Hope this shows the idea. But I would recommend to build a handy UI model.

In Primefaces, adding a row to a table with filtering

I'm using a datatable with filtering. This is the table declaration:
<p:dataTable id="#{tblId}" var="p" editable="true" editMode="cell"
resizableColumns="true" rowIndexVar="rowIndex" selectionMode="multiple"
rowKey="#{p.id}" selection="#{ppselection}"
emptyMessage="No Params in table" value="#{tblValue}" scrollable="true"
style="height:100%" sortMode="multiple" styleClass="#{styleClass}"
filteredValue="#{filteredParams}">
When adding a new row to the table, I want it to already be displayed according to the current filter. i.e. if the filter is "aa" and the row name is "aabbcc" then I want it displayed, but if the row name is "bbcc" then I don't want it displayed. Right now, all I came up with is decidng whether I want to manually add it to the filteredParams list or not.
This is an example of one of the columns in the table, although all the coulmns are filterable:
<p:column width="15%" id="ParameterColumn" headerText="Parameter" sortBy="#{p.name}"
filterBy="#{p.name}" filterMatchMode="contains">
<p:cellEditor id="Parameter">
<f:facet name="output">
<h:outputText id="param_name" value="#{p.name}" />
</f:facet>
<f:facet name="input">
<p:inputText id="nameInput" value="#{p.name}" style="width:99%"
validator="#{p.validateParamName}">
<p:ajax event="change"
update=":main_tabs:paramForm:ParamTbl, :main_tabs:paramForm:SplitedParamTbl" />
</p:inputText>
<p:messages for="nameInput" display="tooltip" />
</f:facet>
</p:cellEditor>
</p:column>
Thanks!!
You can trigger filtering in oncomplete method of ajax/button that adds new row:
oncomplete='tableWidgetVar.filter();'