Pages

Wednesday, March 11, 2009

Smart JSF DataTable Columns

One of the common  and simple requirements of enterprise projects is that stylising your columns based on the data it contains like if the column is displaying a date it should be centered, if its a number it should be aligned right. The following will show you how you can make a smart enough datatable which knows what type needs what style.
I did this on the richfaces datatable but same logic could be used with other datatables.
1. Define the renderer
Since we are using rich faces we need to override the default renderer it comes with:
    <renderer>
<component-family>org.richfaces.Column</component-family>
<renderer-type>
org.richfaces.renderkit.CellRenderer
</renderer-type>
<renderer-class>
org.mca.example.web.renderkit.html.CellAutoAlignedRenderer
</renderer-class>
</renderer>
render-class tag is now CellAutoAlignedRenderer which we will implement.
2. Define the Renderer
The default rich faces renderer is org.richfaces.renderkit.CellRenderer.
We could achive the desired effect by simply overriding the
public String styleClass(FacesContext context, UIComponent component)
method.
import org.richfaces.renderkit.CellRenderer;

public class CellAutoAlignedRenderer extends CellRenderer {

@Override
public String styleClass(FacesContext context, UIComponent component) {
ValueExpression styleExpression = component.getValueExpression("styleClass");
if (styleExpression == null) {
Object value = getValueOfTheOnlyChild(context, component);
if (value instanceof Number) {
return super.styleClass(context, component) + " " + getNumberColumnStyle();
}
else if (value instanceof Date) {
return super.styleClass(context, component) + " " + getDateColumnStyle();
}
}
return super.styleClass(context, component);
}

public String getDateColumnStyle() {
return "dateColumn";
}

public String getNumberColumnStyle() {
return "numberColumn";
}

private Object getValueOfTheOnlyChild(FacesContext context, UIComponent component) {
if (component.getChildCount() == 1) {
UIComponent child = component.getChildren().get(0);
if (child instanceof ValueHolder) {
ValueHolder aValue = (ValueHolder) child;
return aValue.getValue();
}
}
return null;
}

}

"getValueOfTheOnlyChild" method gets the data from the column to determine the data type. "if (value instanceof Number) {" part does determines the style.
"copy paste"

1 comment:

  1. I did similar thing to use dojo.dnd with standard JSF dataTable, but I don't know why renderer doesn't work - it's not use by JSF even I put overriding configuration in my faces-config

    render-kit
    renderer
    component-family javax.faces.Data /component-family
    renderer-type javax.faces.Table /renderer-type
    renderer-class lalala.MyTableRenderer /renderer-class
    /renderer
    /render-kit

    Should I configure that somewhere else?

    ReplyDelete