开发者

Sorting a CellTable server-side

I'm currently using a Gwt CellTable, bound to my GAE/Objectify backend via RPC calls.

All right now! :-)

Then I want to sort columns, so I read http://code.google.com/intl/it-IT/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting

The Async Remote sorting sections shows very well how to get sorting into my AsyncDataProvider but... how can I retrieve the name of the column the user wants to sort?

It shows this code: ColumnSortList sortList = table.getColumnSortList();

But how can I get String names from that? I simply want to know "surname" or "soldDate", the name of the field the column is bound to! Then I will pass it to my rpc service, and use it to sort data server-side query(...).order(<field_name>)

Am I missing something?

UPD: interesting stuff here: http://groups.google.com/group/google-web-toolkit/browse_thread开发者_运维知识库/thread/77a0eaf8086218a6/effb8d3abe69270b#effb8d3abe69270b


You can keep a list of column names ordered as they are in the table:

List<String> columnNames = new ArrayList<String>();

table.addColumn(surnameColumn, "surname");
columnNames.add("surname");

// add the other columns

Then when you need to get the sort column name:

String sortColumnName;
ColumnSortList sortList = table.getColumnSortList();
if (sortList != null && sortList.size() != 0){
     Column <MyEntity, ?> sortColumn = (Column <MyEntity, ?>) 
                                           sortList.get(0).getColumn();
     Integer columnIndex = table.getColumnIndex(sortColumn);
     sortColumnName = columnNames.get(columnIndex);
}

// do your rpc call

*where MyEntity is your data object displayed in the cell table.


A bit late to the party, but here's a more straight-forward solution based off of the current documentation (see section 'ColumnSorting with AsyncDataProvider').

When we're adding our columns we can simply set the dataStoreName:

TextColumn<MyData> surname = new TextColumn<MyData>() {
    ...
}
surname.setSortable(true);
surname.setDataStoreName("surname");  // Set the column name
table.getColumnSortList().push(surname);
table.addColumn(surname, "Last Name");  // eg. A different name for the UI

Then we can retrieve the column's dataStoreName later when sorting:

@Override
protected void onRangedChanged(HasData<MyData> display) {
    ...
    ColumnSortList.ColumnSortInfo info = table.getColumnSortList().get(0);
    String sortColumn = info.getColumn().getDataStoreName();  // Get the column name
    boolean sortIsAscending = info.isAscending();

    rpcService.requestMyData(
        sortColumn,
        sortIsAscending,
        new AsyncCallback<ArrayList<MyData>>() {...}
    );
    ...
}

Using this method we can pass the column name directly to our RPC method. It even allows us to use a different name (eg. the database column name) than the column name used on the UI/client side.


I have used something like this as an application column object.

public class ScrollTableColumn {

    // --------------------------------------------------------------- Field(s)

    private int            sequence;
    private Column         column;
    private Header         header;
    private int            size;
    private int            calculatedSize;
    private boolean        show;
    private PartialColumn  partialColumn;
    private ColumnNameEnum columnName;

}

Now create a HashMap of the above as follows:

Map<Column, ScrollTableColumn> columnMap 
    = new HashMap<Column, ScrollTableColumn>();

Add all the columns as you create them both in the ScrollTableColumn and in the columnMap.

Finally you can get the required name as:

ColumnSortList sortList = dataTable.getColumnSortList();
Column<?, ?> column = sortList.get(0).getColumn();
ColumnNameEnum = columnMap.get(column);
String name = ColumnNameEnum.getName();


The proper way is to extend the base column class which will allow you to override cell rendering, pass in column configuration via your constructor, and most importantly set the DataStoreName which is where you should store the field name for the column. Lastly you should not reuse the onrangechanged fire, but access the columnsort handler directly by overriding it. on range change and column sort handler should call some type of method that you have to update your grid. I call mine updateGrid for sanity. This allows you to set any grid parameters used by your async request to specific sort column and direction. The main reason you want to use column sort handler is to access the ColumnSort event which contains your sort direction information

your column class that extends the base GWT column. You can also extend date or number columns too.

public GridStringColumn(String fieldName, String text, String tooltip, boolean defaultShown, boolean sortable, boolean hidden) {
        super(new TextCell());
        setDataStoreName(fieldName);
        this.text_ = text;
        this.tooltip_ = tooltip;
        this.defaultShown_ = defaultShown;
        setSortable(sortable);
        this.hidden_ = hidden;
    }

create your handler

dataGrid.addColumnSortHandler(new DataGridSortEvent());

your sort event class

protected class DataGridSortEvent implements ColumnSortEvent.Handler {

        @Override
        public void onColumnSort(ColumnSortEvent event) {
            ColumnSortList sortList = dataGrid_.getColumnSortList();
            if (sortList != null && sortList.size() > 0) {
                Column<T, ?> sortColumn = (Column<T, ?>) sortList.get(0).getColumn();
                LOG.info("col_sorta: " + event.isSortAscending());
                LOG.info("col_index: " + sortColumn.getDataStoreName());
                updateDataList();
            }
        }
    }

updateDataList is your method you use to make the actual AJAX request to your server side. rather then logging you sould store this info in private members of your datagrid class so that your request can parameterize them.

you could also make this work for local caching too, just make a copy of the data from your server locally then return a sorted collection of that cached collection, rather then calling the updateDataList method.

Now you do not need to store a separate list for just string names, which is waste of memory not to mention a synchronicity issue if the column order is change from user interaction or whatever.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜