Thursday, July 9, 2009

Persistent Column Widths in Dojo (dojox) DataGrids

Hi everyone, my name is RV David and it's my first time posting on the "DevProducts on Blogger" blog. Hopefully the following will help some of the developers who are scouring the dojo forums/the internet for a solution to achieving persistent column or field widths in the Dojox DataGrid component of the Dojo toolkit.

The DojoX DataGrid Component
The Dojox DataGrid component is simply amazing! It provides a neat and relatively painless way to produce datagrids and is brilliant in the way it handles pagination. It does, however, come with it's limitations.

The RIA
We have recently developed a RIA (Rich Internet Application) for one of our clients which makes full use of the DataGrid component. At any time, we would have a variable number of datagrids displayed on a page in separate Tab Containers for presentation.

We have configured the datagrids so that field widths are adjustable by users. However, once the user either refereshes the page, or navigates to another page, the datagrid is displayed with the default column widths and the users will again have to adjust the field widths to their preference.

Remember DataGrid Column/Field Widths
A request was made for the functionality to "remember" the width of the datagrid columns even after a user navigates to a different part of the application.

The main issue we had is that we could not find a way to (easily) detect that the field width is being resized - there were no onresize event hooks for columns or cells - please correct me if I'm wrong.

The Solution/Workaround
After some reasearch and development, we have come up with the following solution (more like a workaround really) to store field or column widths:

Step 1: Store the Column widths in Cookies
We create a function to traverse through all datagrids and use a naming convention to store field widths in cookies.

function rememberWidths() {
var grids = dijit.registry.byClass('dojox.grid.DataGrid');
grids.forEach(function(grid) {
for (var k in grid.layout.cells) {
var index = grid.layout.cells[k].index;
var field = grid.layout.cells[k].field;
if (field != null && field != "") {
var cookieName = grid.id + field;
dojo.cookie(cookieName, grid.layout.cells[k].unitWidth, {expires:3600});
}
}
});
}

Step 2: Call the function on window.unload.
Add the function to the window object's "onUnload" event so that when the user leaves the page, all field widths are stored in cookies.

dojo.addOnUnload(window, 'rememberWidths');

Alternatively, we could have achieved the same result in one step:

dojo.addOnUnload(window, function() {
var grids = dijit.registry.byClass('dojox.grid.DataGrid');
grids.forEach(function(grid) {
for (var k in grid.layout.cells) {
var index = grid.layout.cells[k].index;
var field = grid.layout.cells[k].field;
if (field != null && field != "") {
var cookieName = grid.id + field;
dojo.cookie(cookieName, grid.layout.cells[k].unitWidth, {expires:3600});
//console.log(cookieName);
}
}
});

Step 3: At this stage, we should now have the widths stored as cookies and can be referenced by the concatenation of the grid id and the field name. For example, we have a "users" datagrid so to retrieve the column width of the id field in the "users" datagrid, we'd call it by using dojo.cookie('usersid');

That's pretty much the concept, although, I must stress that this is a workaround. I kind of feel strange about hooking into the window's onunload event, but hey, this is how we got around it. If you have better solutions, please, share it with us and leave a comment.

2 comments:

rvdavid said...

sorry I had to repost. Blogger kept the old title in the URL and could not find a way to change it.

Europa said...

You can hook into the setColWidth method on the view. This gets called when the column gets resized.

dojo.connect(grid.views.views[0], "setColWidth", function(colIndex,width){
//Save column width
});