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 with List<SortMeta>
does not give me the column details which are currently sorted to carry over to the other page, unlike the load()
method with String 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"
load()
method (I have printed the input parameters value inside load method).Now, do pagination. Here the load()
method fails to give the sorting columns detail
How can I fix this?
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With