In an application there were a few tables filled with results of some queries. I haven’t yet figured out why, but it was of a high importance to the client that all the tables had accumulative sorting (like the order by clause in SQL). This requirement took me a while to figure out how to implement, whilst the solution was quite elegant and pretty small to write it here.
So, there’s a table with results of a search (the query really doesn't matter as the entire sorting solution will be implemented in the view layer)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<table value="#{bindings.CustomerSearch.collectionModel}" var="row" | |
rows="#{bindings.CustomerSearch.rangeSize}" | |
first="#{bindings.CustomerSearch.rangeStart}" banding="row" | |
bandinginterval="1" | |
emptytext="#{bindings.CustomerSearch.viewable ? 'No rows yet.' : 'Access denied.'}" | |
sortlistener="#{CustomersBean.onSort}"> | |
<column sortproperty="Customerid" sortable="true" | |
headertext="#{bindings.CustomerSearch.labels.Customerid}"> | |
<commandlink text="#{row.Customerid}" | |
onclick="return initiateReplacement(#{row.Customerid});" | |
shortdesc="Click to initiate customer replacement"/> | |
</column> | |
<column sortproperty="Surname" sortable="true" | |
headertext="#{bindings.CustomerSearch.labels.Surname}"> | |
<outputtext value="#{row.Surname}"/> | |
</column> | |
<column sortproperty="Name" sortable="true" | |
headertext="#{bindings.CustomerSearch.labels.Name}"> | |
<outputtext value="#{row.Name}"/> | |
</column> | |
<column sortproperty="Fathername" sortable="true" | |
headertext="#{bindings.CustomerSearch.labels.Fathername}"> | |
<outputtext value="#{row.Fathername}"/> | |
</column> | |
<column sortproperty="Address" sortable="true" | |
headertext="#{bindings.CustomerSearch.labels.Address}"> | |
<outputtext value="#{row.Address}"/> | |
</column> | |
</table> |
The whole trick is to set sortListener=”#{CustomersBean.onSort}” for the table. The backing code for this sortListener is found in the backing bean named CustomerBean.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import oracle.adf.view.faces.event.SortEvent; | |
import oracle.adf.view.faces.model.SortCriterion; | |
import oracle.adf.view.faces.component.core.data.CoreTable; | |
import java.util.List; | |
import java.util.ArrayList; | |
public class Customers { | |
public void onSort(SortEvent se) { | |
// get selected criterion | |
List sortList = se.getSortCriteria(); | |
SortCriterion currentSortCriterion = (SortCriterion)sortList.get(0); | |
// get previously selected criteria | |
ArrayList persistentSortList = getCustomerTableSortCriteria(); | |
// the rest of the code expands the sort criteria, applies the new criteria list to the table and saves the criteria list for the future | |
ArrayList updatedSortList = new ArrayList(); | |
updatedSortList.add(0, currentSortCriterion); | |
for(Object o : persistentSortList) { | |
updatedSortList.add((SortCriterion)o); | |
} | |
CoreTable ct = (CoreTable)se.getComponent(); | |
ct.setSortCriteria(updatedSortList); | |
setCustomerTableSortCriteria(updatedSortList); | |
} | |
public static final String CUSTOMER_TABLE_SORT_CRITERIA = "customerTableSortCriteria"; | |
/* As the sort criteria returned at any call to the onSort method have request scope, | |
* I use a session scoped bean that I call viewScope (I clean it up every time the viewId is changed, meaning that user has entered another page) which in fact is a java.util.HashMap. | |
* The method getCustomerTableSortCriteria() returns the Object under key CUSTOMER_TABLE_SORT_CRITERIA stored in viewScope. | |
* Naturally instead of viewScope one can use any other session scoped bean to store the ArrayList of SortCriterion objects. | |
*/ | |
private ArrayList getCustomerTableSortCriteria() { | |
ArrayList sortCriteria = (ArrayList)viewScope.get(CUSTOMER_TABLE_SORT_CRITERIA); | |
if(sortCriteria == null) { | |
sortCriteria = new ArrayList(); | |
setCustomerTableSortCriteria(sortCriteria); | |
} | |
return sortCriteria; | |
} | |
private void setCustomerTableSortCriteria(ArrayList sortCriteria) { | |
viewScope.put(CUSTOMER_TABLE_SORT_CRITERIA, sortCriteria); | |
} | |
} |
And that’s pretty much it. The table is now sortable accumulatively: you can hit customerid first, then name, then surname etc. the resulting table will look similarly to what produces SQL clause order by customerid, name, surname, etc.
Hope this helps.