NOTE: This article is out of date.
Read about the new dgrid for something fresh!

With the release of Dojo 1.2 right around the corner, there’s an updated grid widget available. It offers new features and performance improvements over the existing grid including better Dojo data integration, simplified layout structures, and the ability to enable editing much more easily.

In order to make these improvements, we were forced to break backwards compatibility between the new grid and the old grid. This shouldn’t be a surprise since the grid is part of DojoX. We realized that enough people use, rely on, and extend the grid that we didn’t want to break applications based on Dojo 1.0 and 1.1, so both grids are available to you. The old grid will be available until Dojo 2.0, but it will not be improved in future versions of Dojo 1.x.

This article focuses on the use of the new grid widget. All of the examples presented in this article may be downloaded in a tarball so you can modify and follow along.

Logical File Layout

The new grid API has been organized according to the Dojo conventions. For instance, the old dojox.VirtualGrid is now dojox.grid._Grid, dojox.Grid is now dojox.grid.DataGrid, and dojox.grid.selection is now dojox.grid.Selection. The namespace that objects are in now also reflect where you can find them in the file system.

Dojo Data Integration

I mentioned that dojox.Grid is now dojox.grid.DataGrid, but why is it called DataGrid? The reason is that DataGrid natively supports dojo.data stores. In order to use dojo.data stores with the grid in previous releases, you needed the dojox.grid.data.DojoData model which would bridge the gap between the grid and the store. DataGrid has been engineered to remove that bridge. Instead of using stand-alone models to store data for the grid, any dojo.data store that implements the Dojo Data read API can be used. Additionally, DataGrid can use the write and notification API’s if they are available. Let’s look at an example (using the data from my previous grid tutorials modified to work with ItemFileReadStore):

var jsonStore = new dojo.data.ItemFileReadStore({ url: "json/gaskets.json" });

var grid = new dojox.grid.DataGrid({
	id: 'grid',
	query: { part_num: '*' },
	store: jsonStore,
	structure: layout
}, 'gridNode');

[Live Example]

This will load our JSON file from a URL and give us access to the data through the Dojo Data API. We then pass the store to the DataGrid constructor along with the query we want the grid to run against the store. We’ll get to defining a layout in a bit, but for now let’s look at some more things we can do with this new grid.

I mentioned notification API support. This means if the store changes, the grid will update. Let’s set up an example:

var jsonStore = new dojo.data.ItemFileWriteStore({ url: "json/gaskets.json" });

var grid = new dojox.grid.DataGrid({
	id: 'grid',
	query: { part_num: '*' },
	store: jsonStore,
	structure: layout
}, 'gridNode');

var updateGasketTypes = function(){
	jsonStore.fetch({
		query: { part_num: '??1?' },
		onComplete: function(items, result){
			dojo.forEach(items, function(item){
				jsonStore.setValue(item, "type", 2);
			});
		}
	});
}

[Live Example]

When the button is clicked, any item that has a ’1′ in the third number of its part number will have its type changed to 2 and the grid will update its information.

Layout Structure Simplified

In previous versions of the grid, setting up how you wanted the grid to look was sometimes confusing. With this latest version we have tried to make setting up the look of the grid simpler while still allowing flexibility for those that need it. There are now two ways to lay out your grid: markup and programatically.

Layouts with markup

Previously the only way to set up your grid’s layout for use in markup was with a structure defined in a script block. Those days are long gone! Setting up a grid’s layout is now as simple as this:

Part Number Minimum Temperature Maximum Temperature Type Thickness

[Live Example]

One of the cool features of the grid is that you can group certain columns and lock them from scrolling horizontally. You can set that up with markup as well:

Part Number Minimum Temperature Maximum Temperature Type Thickness

[Live Example]

With colgroup we are able to lock the first column and allow the last four columns to be horizontally scrolled. You can even set up multiple rows within each row while spanning cells between rows and columns:

Part Number Minimum Temperature Maximum Temperature Type
Thickness

[Live Example]

You can even define formatters and getters for columns:

function formatDegrees(value){
	return value + '°';
}

function getODtoID(rowIndex, item){
	if(!item){
		return this.defaultValue;
	}
	var grid = dijit.byId('gridNode');
	var od = grid.store.getValue(item, "outer");
	var id = grid.store.getValue(item, "inner");

	return od - id;
}
Part Number Minimum Temperature Maximum Temperature Type Thickness OD to ID

[Live Example]

Another popular Dojo grid feature is dojox.GridRowView. It provides a view at the left side of the grid that allows you to select rows easily. For Dojo 1.2, that has been renamed to dojox.grid._RowSelector and can be enabled by passing an option to the grid:

Part Number Minimum Temperature Maximum Temperature Type Thickness

[Live Example]

By passing “20px” to the grid in the rowSelector attribute, we are telling the grid we want the row selector to be 20 pixels wide. You can also pass a boolean value (if it’s true, you get the default size) or any other valid css size.

Putting this all together, we can port our previous application to the new API. Just look at the source of here.

Programmatic Layouts

If markup isn’t your thing or you’re creating your grid on the fly you’ll be glad to know that we’ve simplified the structure you pass in to the grid to define the layout. Previously you were required to pass in a structure like this to get something similar to our first markup example:

var layout = [
	// view 0
	{
		cells: [[
			{ field: "part_num", name: "Part Number", width: 'auto' },
			{ field: "min_temp", name: "Minimum Temperature", 
				width: "100px" },
			{ field: "max_temp", name: "Maximum Temperature", 
				width: "100px" },
			{ field: "type", name: "Type", width: "100px" },
			{ field: "thick", name: "Thickness", width: "5em" }
		]]
	}
];

var grid = new dojox.grid.Grid({
	structure: layout,
	model: model
}, 'gridNode');

Now, you can trim it down to something like this:

var layout = [
	{ field: "part_num", name: "Part Number", width: 'auto' },
	{ field: "min_temp", name: "Minimum Temperature", width: "100px" },
	{ field: "max_temp", name: "Maximum Temperature", width: "100px" },
	{ field: "type", name: "Type", width: "100px" },
	{ field: "thick", name: "Thickness", width: "5em" }
];

var grid = new dojox.grid.DataGrid({
	query: { part_num: '*' },
	store: jsonStore,
	structure: layout
}, 'gridNode');

[Live Example]

Multiple rows of cells is also easier. Before we had to do this:

var layout = [
	// view 0
	{
		cells: [[
			{ field: "part_num", name: "Part Number", width: 'auto', 
				rowSpan: 2 },
			{ field: "min_temp", name: "Minimum Temperature", 
				width: "100px" },
			{ field: "max_temp", name: "Maximum Temperature", 
				width: "100px" },
			{ field: "type", name: "Type", width: "100px" }
		],[
			{ field: "thick", name: "Thickness", width: "5em", 
				colSpan: 3 }
		]]
	}
];

var grid = new dojox.grid.Grid({
	structure: layout,
	model: model
}, 'gridNode');

And now:

var layout = [[
	{ field: "part_num", name: "Part Number", width: 'auto', rowSpan: 2 },
	{ field: "min_temp", name: "Minimum Temperature", width: "100px" },
	{ field: "max_temp", name: "Maximum Temperature", width: "100px" },
	{ field: "type", name: "Type", width: "100px" }
],[
	{ field: "thick", name: "Thickness", width: "5em", 
		colSpan: 3 }
]];

var grid = new dojox.grid.DataGrid({
	query: { part_num: '*' },
	structure: layout,
	store: jsonStore
}, 'gridNode');

[Live Example]

If you want to add the row selector, just change the constructor call to this:

var grid = new dojox.grid.DataGrid({
	query: { part_num: '*' },
	structure: layout,
	store: jsonStore,
	rowSelector: '20px'
}, 'gridNode');

[Live Example]

Now you can see the application from my previous post ported to the new programmatic API.

Editing redefined

In order to edit a value in the old grid, you would have to pass an editor class to your cell definition. In the new grid, each cell has a default editor defined; all you have to do is add editable: true to your cell definition and use a store that implements the Dojo Data write API:

var jsonStore = new dojo.data.ItemFileWriteStore({ url: "json/gaskets.json" });

var layout= [
	{ field: "part_num", width: "auto", name: "Part Number" },
	{ field: "min_temp", width: "100px", name: "Minimum Temperature" },
	{ field: "max_temp", width: "100px", name: "Maximum Temperature" },
	{ field: "type", width: "100px", name: "Type" },
	{ field: "thick", width: "5em", name: "Thickness", editable: true }
];

var grid = new dojox.grid.DataGrid({
	query: { part_num: '*' },
	store: jsonStore,
	structure: layout,
	rowsPerPage: 20
}, 'gridNode');

[Live Example]

You can now edit the thickness property of each row of data. What if you don’t want to edit the data with a text box? Let’s say we want to set up a select to edit the type of gasket (cellType for the markup attribute name):

var layout= [
	{ field: "part_num", width: "auto", name: "Part Number" },
	{ field: "min_temp", width: "100px", name: "Minimum Temperature" },
	{ field: "max_temp", width: "100px", name: "Maximum Temperature" },
	{ field: "type", width: "100px", name: "Type", editable: true,
	  type: dojox.grid.cells.Select, options: [ '0', '1' ] },
	{ field: "thick", width: "5em", name: "Thickness", editable: true }
];

[Live Example]

Conclusion

The Dojo 1.2 Grid offers significant performance and API simplifications over previous versions of the Dojo Grid. As of Dojo version 1.2, you will be able to continue using the existing Dojo Grid, and also use the new Grid, even on the same page of an application if necessary. We highly recommend that you upgrade to the new version of the grid as soon as possible as the new feature set is worth the investment!