Primefaces - Custom Pagination/ Sorting load() issue - datatable

We are using Primefaces 3.0.RC2 in our application with seam faces and CDI. We have followed the lazy loaded data table implementation on the component showcase. Since we have a large dataset, we have overridden the load() method to fetch only pagewise results. (vs loading all records in memory at once).
The pagination works as expected, however the sorting does not. The records get sorted correctly the first time the column header is clicked. For all subsequent clicks, the load() method is called twice, sending different values for the sorting order as a result of which, the sort order remains the same on the table. It seems like both the load() calls are being made in the APPLY_REQUEST_VALUES phase.
Can anyone provide any inputs as to why this is happening and how it can be avoided. Any pointers would be highly appreciated.
Some additional info:
As stated earlier, we have overriden the load() method and have it actually query the DB to fetch sorted results pagewise (by specifying max results and order by in the query) and it works fine.
#Override
public List<ABC> load(int first, int pageSize, String sortField, SortOrder
sortOrder, Map<String, String> filters)
{
// Fetch data pagewise from the database
datasource = dao.findPagewiseSortedResults(sortField,
SortOrder.ASCENDING == sortOrder ? true : false, first, pageSize);
// Set the row count
this.setRowCount((int) dao.findTotalCount());
return datasource;
}
However, on clicking the column on the datamodel for sorting, 2 post requests are made.
Find below the xhtml code:
<p:dataTable id="dataTable" var="record"
value="#{testBean.lazyModel}" paginator="true" rows="5"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
selectionMode="single" selection="#{testBean.selectedRecord}"
sortBy="#{record.username}">
<p:ajax event="rowSelect" listener="#{testBean.onRowSelect}"
update=":form:display" oncomplete="accountDialog.show()" />
<p:ajax event="colResize" update=":form:growl"
listener="#{testBean.onResize}" />
<p:column sortBy="#{record.username}"
filterBy="#{record.username}">
<f:facet name="header">
<h:outputText value="User Name" />
</f:facet>
<h:outputText value="#{record.username}" />
</p:column>.........
</dataTable>
We have even upgraded to the latest Primefaces version (3.0.1) but it hasn't helped. Are we missing anything? Any pointers would be very helpful.
Thanks.

Since you are providing the sorting by use of the load() method, you don't have to use dataTable's native sorting tool. You need to remove the sortBy attribute from p:dataTable tag.
The component should be defined this way:
<p:dataTable id="dataTable" var="record"
value="#{testBean.lazyModel}" paginator="true" rows="5"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
selectionMode="single" selection="#{testBean.selectedRecord}" >
EDIT
This way, you'll have your column sortable exactly in the order specified by the client: you will read the SortOrder specified, with the Java code you have posted, and you will use that SortOrder consequently in your implementation of dao#findPagewiseSortedResults()

Related

Ajax event in pagination with Primefaces dataTable not working

I have a "normal" paging with a dataTable. The first "load" brings in 25 items from the database.
In the ajax "page" event I am bringing the following elements in blocks of 25 items. Everything works perfectly with version 5.1 of Primefaces, but in version 5.2 the onPageChange method is not called, in fact paging does nothing.
If in the ajax event "page" I add process="#this" it does call the bean, but not the specified onPageChange method but a start method marked with the #PostConstruct annotation (in this way the same first 25 items and pagination always shows these items).
<p:panel id="..."
header="..."
style="..."
toggleable="true"
toggleSpeed="200" >
<p:dataTable var="some_var"
id="myDataTable"
widgetVar="pag"
first="#{[bean].first}" <-- bean attribute
value="#{[bean].collectionOfObjects}" <-- loading of the first 25 elements
rows="20"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
emptyMessage="..."
lazy="true"
rowIndexVar="rowIndex"
rowStyleClass="#{(rowIndex mod 2) eq 0? '...' : '...'}">
<p:ajax event="page"
listener="#{[bean].onPageChange}"/> <-- load the next 25 items (successively)
<p:ajax event="sort"
listener="#{[bean].orderListing}"/>
<p:column width="..."
headerText="..."
style="..."
sortBy="#{some_var.id}"
id="...">
...
</p:column>
[rest of columns]
</p:dataTable>
</p:panel>
Back (just as an outline):
#PostConstruct
protected void init() {
...
this.collectionOfObjects = new GenericLazyModel<CollectionOfObjects>(...);
}
//Method not called by ajax.
public void onPageChange(PageEvent event) {
//Next 25 items
this.collectionOfObjects = new GenericLazyModel<CollectionOfObjects>(...);
}
Versions: primefaces 5.2, jsf-api 2.2.2, jsf-impl 2.2.2 (updating these last two will be very expensive).
In this post there are several possibilities, but I have not managed to solve the error after reading everything carefully.
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
Thank you very much to all!
Finally, after several tests, I have updated the version of PF to 5.3 and it has worked. The error when updating to this version 5.3 was not from the application itself, it was from the primefaces-extensions library that had to be updated to v4.0.0 (at least). If anyone has a problem updating the PF library, check the version of primefaces-extensions as well.

Primefaces dataTable single selection validation

I can validate a p:selectOneMenu like this:
<p:selectOneMenu id="eventTimezoneDropdown"
value="#{myBean.eventTimeZone}"
required="true"
requiredMessage="The TimeZone must be specified."
effect="none">
<f:selectItems value="#{myBean.timeZoneItems}"/>
</p:selectOneMenu>
Conceptually speaking, using a p:dataTable with single row selection will achieve the same goal - it allows you to select one row using a selection attribute instead of value attribute and using value attribute instead of <f:selectItems>.
<p:dataTable id="ActivitiesTable" var="row"
value="#{myBean.rows}"
selection="#{myBean.selectedRow}"
rowKey="#{row.activityId}">
<p:column selectionMode="single"/>
...
</p:dataTable>
However I don't see any validation options (e.g. a required attribute) on the p:dataTable.
Is there a way or workaround to have a required selection validation on a p:dataTable similar to the required attribute on p:selectOneMenu?
Environment: Primefaces 5.3, JSF 2.2.8-14, Tomcat 7.0.68.
what i know in primefaces there are not this functionality in datatable, but you can play with your code,
i suggest that you can do the same event in your ManagedBean, so you can check if a row is selected or not, if yes then ok else you can create a simple message, that notifie the user that the selection of a row is required like that:
public void requiredSelect() {
if (myObject == null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error", "My object is required!"));
}
}
Another way to work around this issue is by using a hidden input field, bound to the same value which gets updated on row select.
<p:dataTable id="ActivitiesTable" var="row"
value="#{myBean.rows}"
selection="#{myBean.selectedRow}"
rowKey="#{row.activityId}">
<p:ajax event="rowSelectRadio" update="#parent:hiddenTimezoneInput"
<p:column selectionMode="single"/>
...
</p:dataTable>
<h:inputHidden id="hiddenTimezoneInput" value="#{myBean.selectedRow}"
required="true" requiredMessage="The TimeZone must be specified."/>
This way, you can add regular validators on the inputHidden (such as required) and have it processed on form submit.

In <p:dataTable> pagination not working with dynamicColumns+lazy+sorting

i'm having a lazyloading Datatable with dynamic columns generated
this is my dataTable
<p:dataTable var="iterator" id="dataTable"
value="#{MyManagedBean.lazyModel}"
paginator="true" rows="20"
lazy="true">
<p:columns value="#{MyManagedBean.columns}" var="column"
columnIndexVar="colIndex"
sortBy="#{iterator[column.property]}"
filterBy="#{iterator[column.property]}">
<f:facet name="header">
#{column.header}
</f:facet>
#{iterator[column.property]}
</p:columns>
</p:dataTable>
this works perfect without pagination. if i paginate, load() method does not give the SortField value, instead it gives me "property]"
can one help me in fixing this...
I believe this is a Primefaces bug.
I think the correct sort details should be passed to LazyDataModel.load() when paging in order to use in in your DB query.
Adding
|| (table.isLazy() && table.isPaginationRequest(context))
to the shouldDecode method in org.primefaces.component.datatable.feature.SortFeature should resolve this issue.
public boolean shouldDecode(FacesContext context, DataTable table) {
return isSortRequest(context, table) || (table.isLazy() && table.isPaginationRequest(context));
}
I've crated a new issue:
https://code.google.com/p/primefaces/issues/detail?id=7068

populate primefaces datatable from a nativeQuery

im learning jsf enviroment, sry if this is kind of easy case for you ,
Im trying to populate a primefaces datatable from a native query , this is what i got at the moment
//My native query is defined in my entity
#NamedNativeQueries({#NamedNativeQuery(name="Tallt089.bandejaCitas",
query ="select bandeja.ep_id_tallt089 idBandeja ...)})
...
...
I call this nativeQuery this way
public List**<TablaBandejaCitas>** bandejaCitas(String cia, String agencia, String division) {
Query query = em.createNamedQuery("Tallt089.bandejaCitas");
query.setParameter(1,cia);
query.setParameter(2,agencia);
query.setParameter(3,division);
return query.getResultList();
//this works fine retrieves correctly my query
}
And use it on my managedBean
public List**<TablaBandejaCitas>** bandejaCitas(String compania,
String agencia,String division){
return agendamientoSession.bandejaCitas(compania,agencia,division);
}
then referenced this on my jsf page like this
<p:dataTable id="bandeja_citas"
value="#{AgendamientoMBean.bandejaCitas(UsuarioMBean.compania,UsuarioMBean.agencia,
UsuarioMBean.divisionPK.diDivision)}"
var="bandeja"
paginator="true" rows="15" >
<f:facet name="header">
Bandeja Citas por confirmar/Llamadas por realizar
</f:facet>
<p:column headerText="Id Bandeja" >
<h:outputText value ="#{bandeja.idBandeja}"/>
</p:column>
<p:column headerText="Cliente" sortBy="#{bandeja.cliente}"
filterBy="#{bandeja.cliente}">
<h:outputText value ="#{bandeja.cliente}"/>
</p:column>
...
...
...
</p:dataTable>
I realized that the var property needs something like mapped of the fields of the query because the warnings on the jsf page tell me that this is an unkwon property
<h:outputText value ="#{bandeja.**cliente**}"/>
I dont know how to store the query in that variable so the data can be displayed
right now i got a for input string exception like the component its reading raw data instead of formmatted list with the correct variable filled with the query fields ..
hope you can understandme
apreciatte your comments in advance :D
Ok, I solved this little problem. I did it by creating an entity class (even is not a table in the DB) with the columns that I select in the nativeQuery and then using this class as the resultClass option in the native:
resultClass=com.talleresZeusWeb.entidades.BandejaCitas.class
I was trying to make that sqlresultsetmapping annotation but don't know to use it in this case.
Hope someone finds this useful at some point, thank you for your responses #Rich

Primefaces LazyModel datatable always calls for first=0 pageSize=10

I am using the LazyDataModel to populate a a table with 33 items(A sub set of a long list of parts and can grow or shrink) in pages of 10. the table deceleration is as follows
<p:dataTable var="spare" value="#{sitePartController.selectParts}" paginator="true" lazy="true"
currentPageReportTemplate="(Entries: {startRecord} - {endRecord} of {totalRecords}, Page: {currentPage}/{totalPages})"
paginatorTemplate="{CurrentPageReport}{FirstPageLink}{PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}"
rows="10" selection="#{sitePartController.selectedParts}"
paginatorAlwaysVisible="false"
dynamic="true"
>
The pagination works fine filling the currentPageTemplate with 33 items 4 pages 1- 10 etc. When i press a link all the pagination output changes correctly(page 2/4 etc). However the data in the table does not change, just continues to show records 0-9. My override Load method is as follows.
selectParts = new LazyDataModel() {
#Override
public List<SitePart> load(int first, int pageSize, String string, boolean bln, Map map) {
return getSiteSpares(first,first+pageSize);
}
};
int totalRowCount = getSparesCount();
selectParts.setRowCount(totalRowCount);
When I stop my debug in the load method no matter which datatable pagination link I select; first is always 0 and page is 10 (as expected). How do I get the datatable to send the correct first index or have I missed something fundamental in the last 6 hours of googleing and trying various alternatives.
Not sure if it could cause the issue, but shouldn't it be:
selectParts = new LazyDataModel<SitePart>(){
Try to put p:dataTable inside h:form
<h:form id="form">
<p:dataTable>
</p:dataTable>
</h:form>

Resources