Showing posts with label Facelets. Show all posts
Showing posts with label Facelets. Show all posts

Sunday, January 18, 2009

External Sorting in seam application with rich:dataTable

When working with seam application you may have encountered a scenario where you have to implement rich:dataTable in a non-conventional way , for example look at the below fragment


NORMAL WAY





Symbol

#{aRow.symbol}




Quantity

#{aRow.quantity}


...
..
A MORE FLEXIBLE WAY..






Symbol
Quantity



#{aRow.symbol}



#{aRow.quantity}




notice the second case, that we are not defining the table headers with "header" facet for each column, instead we are defining all the header columns using a single header facet. This allows me to do stuff like detail rows for each row using subtable and columngroups easily. This approach brings a problem too, it is not easy to define sorting information to take advantage of automatic sorting feature of dataTable. Rich faces demo gives an nice example of using external sorting, but it may not be very obvious on how to implement sorting by clicking on header rows, atleast for me it was little difficult to get around this problem. Actually it is not that difficult , here is how hey do it....

1. We need to make use of dataTable's sortPriority property to tell dataTable which column the table should be sorted on.
2. Define IDs for all the columns you want to provide sorting ability
3. Make the header clickable and on click event change the sort priority (dont worry if this is not clear, I will explain you in detail.. shortly)


Because we need to use the same feature for many screens , we will not write anything in our conversation scoped sessionbeans , instead we will define a reusable bean which can store the sortPriority and sortOrder , as per rich faces documentation I named the bean SortingBean, less surprising. huh..

it is a simple bean which holds the current sort column and sortingOrder (ASCENDING or DESCENDING), here is the class

package com.dezinx.shareguru.utils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SortingBean implements Serializable {

/**
*
*/
private static final long serialVersionUID = 3478316227248532205L;

private String sortingOrder;
private List sortingPriority;

public SortingBean() {
sortingOrder = "ASCENDING";
sortingPriority = new ArrayList();
}

public void sortOn(String columnName) {
if (sortingPriority.contains(columnName)) {
toggleSortingOrder();
} else {
sortingPriority.clear();
sortingPriority.add(columnName);
sortingOrder = "ASCENDING";
}
}

private void toggleSortingOrder() {
if (sortingOrder.equals("ASCENDING"))
sortingOrder = "DESCENDING";
else
sortingOrder = "ASCENDING";
}

public String getSortingOrder() {
return sortingOrder;
}

public void setSortingOrder(String sortingOrder) {
this.sortingOrder = sortingOrder;
}

public List getSortingPriority() {
return sortingPriority;
}

public void setSortingPriority(List sortingPriority) {
this.sortingPriority = sortingPriority;
}
}


Now we have to expose this sortingBean to the view and it can be easily done by outjecting the instance of SortingBean , like below, in your seam action (stateful session bean)


.....
@Out(scope=ScopeType.CONVERSATION)
SortingBean sortingBean;
...




Finally , lets define the view


..





Price



Quantity




#{aRow.price}



#{aRow.quantity}





in the above code, take notice of how we set selfSorted property to false , defined column ids to refer in a:support , which fires an ajax request to set the current column to sort, Also notice that a:support has reRender attribute set to the id of dataTable, which will force a table rerender after click on table header.

Hope this helps.

Monday, November 17, 2008

Changing Effects without resorting to javascript in RichFaces JSF

Recently I had to use <rich:effect> to make a richPanel appear with BlindDown effect on user action. It was easy for me as I just had to use code as below to accomplish this

 
.....





Just as it was given in RichFaces Demo site. Now I had to do this tricky part, I have to show the panel when user clicks the link "click" for the first time and BlindUp to close the panel when clicked again. I know we can easily do it with javascript as it just uses the scriptaculous library, I wanted to avoid javascript (rather explicitly in JSF applications), so came up with this solution.

As I will be toggling the effect for panel based on the values that I am going to display from my seam action, i wanted to use the data to differentiate if I need to show or hide the panel

 
.....








Note that the oncomplete handler is unchanged (where I thought I will have to call a different javascript here initially ..), we will be changing the effect type based on our business specific condition which can help us determine whether to close the panel or to open it.

Also notice, that the style element for the richPanel is set to display:none or display:block , this is to hide the panel initially so that BlindDown effect make sense.. and similarly used display:block to make sure user can see the effect of panel hiding using the BlindUp effect


..

..