Reputation: 9559
I am trying to extends GWT's DataGrid capabilities for my own project and would like to add the ability to filer columns. I have successfully rendered a filter box in the Header, but it is not responding to events.
Following is the relvant part of my code, which has been adapted from the code given here: CellTable with custom Header containing SearchBox and Focus Problem
The question above does not quite fit my needs, as it does not work if the columns are sortable.
Instead, I have developed a header consisted of 2 table rows (TR's), the top row containing filter boxes, the 2nd row containing column titles and responding to Sort events. The Sort events work OK, but the filter boxes to not respond to any events. Here's the code:
class HeaderBuilder extends AbstractHeaderOrFooterBuilder<Record> {
//HTML to render an Input Box
private InputBoxHTML inputBox = GWT.create(InputBoxHTML.class);
//List of columns in the table
private List<ListGridColumn<?>> columns = new ArrayList<ListGridColumn<?>>();
//Constructor. ListGrid is the outer class extending DataGrid
private HeaderBuilder() {
super(ListGrid.this, false);
}
@Override
protected boolean buildHeaderOrFooterImpl() {
TableRowBuilder tr = startRow();
tr.startTH().endTH(); //extra column
//Create top row of column headers - filter boxes for filterable columns, empty cells for non-filerable
for (ListGridColumn<?> column : this.columns) {
TableCellBuilder th = tr.startTH();
Header<String> header;
//If this column is filterable...
if (column.filter) {
//Create a new Cell containing an Input Box
AbstractCell<String> cell = new AbstractCell<String>("click","keydown","keyup") {
public void render(Context context, String value, SafeHtmlBuilder sb) {
sb.append(inputBox.input(""));
}
public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event, ValueUpdater<String> valueUpdater) {
//These events never fire!
Window.alert("event");
}
};
header = new Header<String>(cell) {
public String getValue() {
return "value";
}
};
} else {
//Empty cell for non-filterable columns
header = new TextHeader("");
}
Context context = new Context(0, 0, header.getKey());
renderHeader(th, context, header);
th.endTH();
}
tr.endTR();
//Bottom row : header captions & sorting. This all works OK
tr = startRow();
tr.startTH().endTH(); //extra column
for (ListGridColumn<?> column : this.columns) {
TableCellBuilder th = tr.startTH();
enableColumnHandlers(th, column);
Header<String> header = new TextHeader(column.headerStr);
Context context = new Context(0, 0, header.getKey());
if (column.sortKey!=null) {
this.renderSortableHeader(th, context, header, true, true);
} else {
this.renderHeader(th, context, header);
}
th.endTH();
}
tr.endTR();
return true;
}
}
Upvotes: 3
Views: 3501
Reputation: 3207
If you looks in the source code of insertColumn(int beforeIndex, Column col, Header header, Header footer) method in AbstractCellTable class (which is extended by DataGrid and CellTable), when a column is inserted (or added) all the events for the header (cell or footer) are sinked in order to propagate it from the table to the corresponding cell:
if (header != null) {
Set<String> headerEvents = header.getCell().getConsumedEvents();
if (headerEvents != null) {
consumedEvents.addAll(headerEvents);
}
}
...
CellBasedWidgetImpl.get().sinkEvents(this, consumedEvents);
You're declaring the Headers in the builder but not "registering" it, therefore events are not propagated to the header cell. You should find a way to register it. I don't see any clean solution because DataGrid can not be easily extended.
I can purpose you two dirty ones:
Create your version of DataGrid (you need to copy and paste the code and declared it in the same package of DataGrid) and modify it in order to register two header for column.
Create a new Header capable of propagate the events to the correct instance of the two headers in the column.
I will go for 2, creating an header with two cell inside, you can use these two cell in the builder.
Upvotes: 2