sortMode="multiple" and lazy="true" in <p:dataTable> clears multisort meta during pagination
I solved this question in a temporary way... Have a sessionscoped managed bean for storing the sorting column details, inorder to get within load() during pagination, like:-
@ManagedBean
@SessionScoped
public class StoreSortColumnDetail implements Serializable{
/** holds multisort values**/
private List<SortMeta> mMultiSortMeta;
public List<SortMeta> getMultiSortMeta() {
return mMultiSortMeta;
}
public void setMultiSortMeta(List<SortMeta> multiSortMeta) {
mMultiSortMeta = multiSortMeta;
}
public void clearMultiSortMeta() {
if(this.mMultiSortMeta != null)
this.mMultiSortMeta.clear();
}
}
and use it in load() as like this:
@Override
public List<Car> load(int first, int pageSize,
List<SortMeta> multiSortMeta,Map<String, String> filters) {
/** Instance to the SessionScoped scoped StoreSortColumnDetail managed bean*/
@ManagedProperty(value="#{StoreSortColumnDetail }")
private StoreSortColumnDetail storeSortColumnDetail ;
public void setStoreSortColumnDetail (StoreSortColumnDetail sortColumnDetail ) {
this.storeSortColumnDetail = sortColumnDetail ;
}
/** to hold the handled sort column detail**/
List<SortMeta> handledMultiSortMeta = new ArrayList<SortMeta>();
/*Here starts the multisortmeta handling process*/
/** check for List<SortMeta> for null**/
if(multiSortMeta != null ) {
/** updates StoreSortColumnDetail's List<SortMeta> with Load()'s List<SortMeta>**/
storeSortColumnDetail.setMultiSortMeta(multiSortMeta);
handledMultiSortMeta = multiSortMeta;
}
/** check for List<SortMeta> for notnull **/
else if (multiSortMeta == null) {
/**assigns Load()'s List<SortMeta> with StoreSortColumnDetail's List<SortMeta>**/
handledMultiSortMeta = storeSortColumnDetail.getMultiSortMeta();
}
/*Now u have handled multisortmeta from load()...
and u can process now from handledMultiSortMeta*/
}
i hope u came to know how i handled, if not intimate me... but this is a temporary way,need to handle it through primefaces way...
senthil_sss
Updated on June 07, 2022Comments
-
senthil_sss almost 2 years
I just enabled multiple sorting in the showcase code for "DataTable - Lazy Loading"
datatableLazy.xhtml
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>CarDataTable</title> </h:head> <h:body> <h:form id="form"> <p:dataTable var="car" value="#{tableBean.lazyModel}" paginator="true" rows="10" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15" id="carTable" lazy="true" sortMode="multiple"> <p:ajax event="rowSelect" listener="#{tableBean.onRowSelect}" update=":form:display" oncomplete="carDialog.show()" /> <p:column headerText="Model" sortBy="#{car.model}" filterBy="#{car.model}"> <h:outputText value="#{car.model}" /> </p:column> <p:column headerText="Year" sortBy="#{car.year}" filterBy="#{car.year}"> <h:outputText value="#{car.year}" /> </p:column> <p:column headerText="Manufacturer" sortBy="#{car.manufacturer}" filterBy="#{car.manufacturer}"> <h:outputText value="#{car.manufacturer}" /> </p:column> <p:column headerText="Color" sortBy="#{car.color}" filterBy="#{car.color}"> <h:outputText value="#{car.color}" /> </p:column> </p:dataTable> </h:form> </h:body> </html>
TableBean.java
package com.solartis.primefaces.sample; import java.util.ArrayList; import java.util.List; import java.util.UUID; import javax.faces.bean.ManagedBean; import org.primefaces.model.LazyDataModel; @ManagedBean public class TableBean { private LazyDataModel<Car> lazyModel; private Car selectedCar; private List<Car> cars = new ArrayList<Car>(); private final static String[] colors; private final static String[] manufacturers; static { colors = new String[10]; colors[0] = "Black"; colors[1] = "White"; colors[2] = "Green"; colors[3] = "Red"; colors[4] = "Blue"; colors[5] = "Orange"; colors[6] = "Silver"; colors[7] = "Yellow"; colors[8] = "Brown"; colors[9] = "Maroon"; manufacturers = new String[10]; manufacturers[0] = "Mercedes"; manufacturers[1] = "BMW"; manufacturers[2] = "Volvo"; manufacturers[3] = "Audi"; manufacturers[4] = "Renault"; manufacturers[5] = "Opel"; manufacturers[6] = "Volkswagen"; manufacturers[7] = "Chrysler"; manufacturers[8] = "Ferrari"; manufacturers[9] = "Ford"; } public TableBean() { populateRandomCars(cars, 50); lazyModel = new LazyCarDataModel(cars); } public Car getSelectedCar() { return selectedCar; } public void setSelectedCar(Car selectedCar) { this.selectedCar = selectedCar; } public LazyDataModel<Car> getLazyModel() { return lazyModel; } private void populateRandomCars(List<Car> list, int size) { for (int i = 0; i < size; i++) { list.add(new Car(getRandomModel(), getRandomYear(), getRandomManufacturer(), getRandomColor())); } } private String getRandomColor() { return colors[(int) (Math.random() * 10)]; } private String getRandomManufacturer() { return manufacturers[(int) (Math.random() * 10)]; } private int getRandomYear() { return (int) (Math.random() * 50 + 1960); } private String getRandomModel() { return UUID.randomUUID().toString().substring(0, 8); } }
LazyCarDataModel.java
package com.solartis.primefaces.sample; import java.util.ArrayList; /** * Dummy implementation of LazyDataModel that uses a list to mimic a real datasource like a database. */ public class LazyCarDataModel extends LazyDataModel<Car> { private List<Car> datasource; public LazyCarDataModel(List<Car> datasource) { this.datasource = datasource; } @Override public Car getRowData(String rowKey) { for(Car car : datasource) { if(car.getModel().equals(rowKey)) return car; } return null; } @Override public void setRowIndex(int rowIndex) { if (rowIndex == -1 || getPageSize() == 0) { super.setRowIndex(-1); } else super.setRowIndex(rowIndex % getPageSize()); } @Override public Object getRowKey(Car car) { return car.getModel(); } @Override public List<Car> load(int first, int pageSize, List<SortMeta> multiSortMeta,Map<String, String> filters) { System.out.println("\nTHE INPUT PARAMETER VALUE OF LOAD METHOD : \t"+"first=" + first + ", pagesize=" + pageSize + ", multiSortMeta=" + multiSortMeta + " filter:" + filters); System.out.println("\nTHE MULTISORTMETA CONTENT : \t"); if (multiSortMeta != null) { for (SortMeta sortMeta : multiSortMeta) { System.out.println("SORTFIELD:" +sortMeta.getSortField()); System.out.println("SORTORDER:" +sortMeta.getSortOrder()); System.out.println("SORTFUNCTION:" +sortMeta.getSortFunction()); System.out.println("COLUMN:" +sortMeta.getColumn()); System.out.println("CLASS:" +sortMeta.getClass()); } } List<Car> data = new ArrayList<Car>(); //filter for(Car car : datasource) { boolean match = true; for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) { try { String filterProperty = it.next(); String filterValue = filters.get(filterProperty); String fieldValue = String.valueOf(car.getClass(). getField(filterProperty).get(car)); if(filterValue == null || fieldValue.startsWith(filterValue)) { match = true; } else { match = false; break; } } catch(Exception e) { match = false; } } if(match) { data.add(car); } } //rowCount int dataSize = data.size(); this.setRowCount(dataSize); //paginate if(dataSize > pageSize) { try { return data.subList(first, first + pageSize); } catch(IndexOutOfBoundsException e) { return data.subList(first, first + (dataSize % pageSize)); } } else { return data; } } }
It works well except when I paginate with multiple columns sorting, the
load()
method withList<SortMeta>
does not give me the column details which are currently sorted to carry over to the other page, unlike theload()
method withString sortField, SortOrder sortOrder
which gives those sorting details.For example:
-
Click on the sorting arrow in "manufacturer" and then Ctrl+click on the sorting arrow of "year"
- you would get the sorting column details to the
load()
method (I have printed the input parameters value inside load method).
- you would get the sorting column details to the
-
Now, do pagination. Here the
load()
method fails to give the sorting columns detail- not only for pagination, if you enter column filter values after clicking on the sorting columns, the same problem exist
How can I fix this?
-
-
senthil_sss almost 11 years@Tiny: plz..take a look at my answer and give ur comments
-
Tiny almost 11 yearsYeah! Thank you for answering this question. I will see this later in a few days, since I'm currently a bit busy with other stuff for a few days. Please keep it up. Don't delete it.
-
Tiny almost 11 yearsYes, I gave it a try and it worked great. Nevertheless it is still incomplete to meet my requirements because
sortColumn
should be retained (with column highlight and sort derection) on the client-side even afterdataTable
is rendered i.e when<p:commandButton>
is pressed to add a row into the database and consequently intodataTable
which doesn't happen util some JavaScript magic is used. I tried the answers to this question but unfortunately none of them worked for me as expected. Did you do that in your application? Thanks so much. -
senthil_sss almost 11 years@Tiny: unfortunately i didn't take up ur scenario.I will try urs and inform u soon
-
senthil_sss almost 11 years@Tiny: can u get me something to this unrelated issue : stackoverflow.com/questions/17145023/…
-
Tiny almost 11 yearsI've looked into your previous question. Until now, I didn't use
<cc:interface>
and<cc:implementation>
though I gave it a try after reading some tutorials but it didn't work for me. It requires me to spend sometime on it. Therefore, I'm right now unable to see the cause of that exception, sorry. Nevertheless, I'll keep trying though, hoping you'll get answer(s) before that. (I'm currently more comfortable in Spring than JSF). -
senthil_sss almost 11 years@Tiny : ok..no probs..i'll reply u soon,regarding ur scenario!!.
-
Tiny almost 11 yearsBack to my previous comment : if it doesn't work reasonably, then I want to start a bounty on your question to see, if someone has a reliable solution or not. If not, then I want to leave Primefaces forever because in addition to this issue in the question, I found so many other issues in this framework (with the status "WontFix" in the next release or so) and many of them are likely to be encountered on its way. My application is pending for months because of these issues. Thank you very much for your help, sir.
-
Kukeltje over 8 yearsIf you override core PF classes, it is good to also state which version this was for! (it is good to mention version info at all times as a matter of fact)
-
YamYamm over 8 yearsyou are correct, i believe this solution is good for any primefaces version above 5.0, also overriding is not mandatory here, i meant directly using concrete BeanPropertyComparator class by instantiating a new object.