Storing Table Preferences - Column Order and Visible Columns

In our application, we’d like to persist the user preferences for all tables so they are retained among sessions. This means storing which columns the user has set as visible, and the way he/she has ordered the columns.

I see through Firebug that an ajax request is initiated when the user hides and shows columns. This is good because this action can be captured on the server side and later persisted either in a cookie or to the database.

My question is about the reordering of columns. On the demo site, it doesn’t look like a server request is initiated upon this action, so must be happening entirely in JavaScript:

Is there some way this user-initiated action could be captured on the server side? Or is the only option to add a control to the page, like a button, that the user must click in order to save the preferences, and then write code to inspect the table at that time?

I’m no expert, but I found you could code like this when your view is unloaded:

	public void detach() {
		for( Object o : table.getVisibleColumns() ) {
                        // These are string property ids of the column names like name, description, status, lastUpdatedTimestamp
			_logger.debug("detach() - visible columns[]: " + o); 

It says they are delivered in the order they are in, but if there’s no message sent to the server when the user reorders them, it seems unlikely to work as you’d like.

Thanks David. That will work just fine, and will be efficient to store all preferences related to the table at the time its detached.

Been thinking a bit more about this. I believe users will establish their preferences when the new app is launched, and make only minor adjustments after that. So, checking this every time on detach() could be a bit wasteful.

I’ve not tried the exercise yet of building a custom component. I’m wondering if its possible to create one that extends from the Vaadin table. Basically all default behavior should remain the same, but on the JS side when a column is moved, I’d like to issue an ajax request to inform the server side code. Anyone know if this is possible, at least in theory?

It is possible, although the Table component (and its VScrollTable widget) is definitely not the easiest place to start doing something like this.

You need to replace the VScrollTable with your own implementation. The easiest and cleanest way is probably to subclass it and then indicate in your widgetset that you want to use your version instead of the standard VScrollTable. Search for “GWT deferred bindings” and “replace-with” for more info on how to do this. Alternatively, you can use the @ClientWidget annotation in your server side subclass of Table, as you will have one anyway. In either case, don’t forget to recompile the widgetset.

I hope you will not need a full copy of VScrollTable but only need to override one method in a subclass - probably reOrderColumn(). It already calls client.updateVariable(paintableId, “columnorder”, columnOrder, false), but the first problem is the “false” - the change is not sent to the server immediately but queued to wait for other actions. If your subclass calls the method from the superclass and then makes an immediate update for (any) variable of the paintable, also the column order change is sent.

On the server side, Table.setColumnOrder() is private, so you might need to override Table.changeVariables() and duplicate a few lines of code from it.

You could also
create an enhancement request
to have these changes sent immediately to the server if the table is in immediate mode, and to get an event based on the change on the server side.

Haven’t ever done a ticket before, but I’d vote for that since it’s generally useful too Vaadin programmers.

In a UI framework, it is important that you can remember client actions so you can restore state. When people go to the trouble to change visible columns, reorder them, change sort order, like resizing a window, it’s something useful to know. The current position of a window would be great, too. This way the user doesn’t have to re-do these preferences manually each time they revisit a view.

Thanks for the advice David and Henri. I’ve opened a ticket for the enhancement: