I've been tasked with implementing sorting & filtering of data displayed in a GWT CellTable.
Thankfully GWT already supports sorting, but it looks like I'll have to hack together my own filtering support.
To be more precise, what I'm trying to support is similar to the filtering offered by Excel, whereby you can click on a drop-down menu in the column headers and (for example) click checkboxes that will allow you to filter the rows based on the values for the filtered column(s). A picture is worth a thousand words:
My question: any suggestions on how to go about implementing this in GWT 2.2? Is it even possible?
One option I'm thinking about is to pass in a custom Header object to CellTable.addColumn(). If it's possible, I'll add a ClickHandler to the Header, and then open a Popup that displays a widget for filtering. Not sure how to implement this without negatively affecting the sorting behavior.
Any suggestions gladly welcome.
Edit:
Thanks to John below, I've got the following FilterableHeader
class that allows me to at least put an icon into the header. Unsure how to get a ClickHandler on that icon just yet, as the image is inserted via HTML rather than using GWT widgets.
public class FilterableHeader extends Header<String>
{
/**
* Image resources.
*/
public static interface Resources extends ClientBundle
{
ImageResource downArrow();
ImageResource upArrow();
}
private static final Resources RESOURCES = GWT.create(Resources.class);
private static final int IMAGE_WIDTH = 16;
private static final String DOWN_ARROW = makeImage(RESOURCES.downArrow());
private static final String UP_ARROW = makeImage(RESOURCES.upArrow());
private static String makeImage(ImageResource resource)
{
AbstractImagePrototype proto = AbstractImagePrototype.create(resource);
return proto.getHTML().replace("style='", "style='position:absolute;right:0px;top:0px;");
}
private String text;
public FilterableHeader(String text)
{
super(new ClickableTextCell());
this.text = text;
}
@Override
public String getValue()
{
return text;
}
@Override
public void render(Cell.Context context, SafeHtmlBuilder safe)
{
int imageWidth = IMAGE_WIDTH;
StringBuilder sb = new StringBuilder();
sb.append("<div style='position:relative;cursor:hand;cursor:pointer;");
sb.append("padding-right:");
sb.append(imageWidth);
sb.append("px;'>");
sb.append(UP_ARROW);
sb.append("<div>");
sb.append(text);
sb.append("</div></div>");
safe.append(SafeHtmlUtils.fromSafeConstant(sb.toString()));
}
}
Best Answer
Custom headers are what is used with GWT 2.1 to do sorting. The 2.1 bikeshed has examples that use custom headers and am using one for sorting until Mvp4g moves to 2.2. To enable the filtering, just add an image with its own click handler and you should be good - it won't trigger sort behavior when it's clicked on, just the rest of the header will.
For the actual filtering, if you're using the database model from the examples (the wrapper class for the ListDataProvider), then I'd think you'd just keep two lists - the filtered list that's assigned to the ListDataProvider, and the unfiltered list it's based on.
Hope that helps!
In your new sample code, you might want to try a CompositeCell with the ClickableTextCell inside it, along with an ActionCell for the filtering part - if you can stick an image into the ClickableTextCell, you should be able to in the ActionCell, plus it'll have the mouseup behavior you want.