I write solutions to the problems I can't find much about elsewhere on the Web, also some code/script snippets that are absolutely awesome and make my life easier. Will be glad if someone finds these posts interesting and helpful!

Monday, May 3, 2010

Accumulative sorting in ADF 10g tables

Just what the title says.

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)
<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>
view raw gistfile1.xml hosted with ❤ by GitHub

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.
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);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

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.

No comments:

Post a Comment