Hello dgrid!

The dgrid project was conceived by engineers at SitePen with the goal of creating a next-generation grid component that takes full advantage of modern browsers and the new features in modern Dojo. It is designed to be lightweight, modular, and easily extensible, and is released under the same licensing and CLA as the Dojo Toolkit.

Obtaining dgrid

To get started with dgrid, you must first download it. You can do this by going to the GitHub repository for dgrid and following the instructions in the README.

dgrid is one of the first new Dojo packages to be distributed standalone instead of as a part of the DojoX namespace. This distribution model is part of a shift toward a distributed component development model in Dojo 2, made possible by advances in distributed code services like GitHub.

Getting started with dgrid

In order to use dgrid, we start by loading Dojo 1.8+ and the dgrid Grid module, along with dgrid's structural CSS:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Tutorial: Hello dgrid!</title>
	<link rel="stylesheet" href="path/to/dgrid/css/dgrid.css">
</head>
<body>
	<div id="grid"></div>
	<!-- this configuration assumes that the dgrid package is located
	     in the filesystem as a sibling to the dojo package -->
	<script src="path/to/dojo.js"
		data-dojo-config="async: true"></script>
	<script>
		require([ 'dgrid/Grid', 'dojo/domReady!' ], function (Grid) {
			var grid = new Grid({ /* options here */ }, 'grid');
			…
		});
	</script>
</body>
</html>

If you're migrating from earlier versions of dgrid, note that you must load dgrid.css yourself in dgrid 1.0, as the xstyle dependency has been dropped. If you don't need all of the structural styles, you can use Stylus to import just the specific parts you need (starting with dgrid/css/base.styl at minimum).

With this skeleton code in place, in order to actually create a useful grid, we need to define two things: the structure of the grid, and the data we want to use. The structure of the grid should be passed in the columns key and can be defined in one of three ways:

1. As an array of objects with explicit field and label properties:

var columns = [
	{
		field: 'first',
		label: 'First Name'
	},
	{
		field: 'last',
		label: 'Last Name'
	},
	{
		field: 'age',
		label: 'Age'
	}
];

2. As a hash map, where the key is used as the "field" and the value is an object containing a "label" property:

var columns = {
	first: {
		label: 'First Name'
	},
	last: {
		label: 'Last Name'
	},
	age: {
		label: 'Age'
	}
};

3. As a hash map, where the key is used as the "field" and the value is used as the "label":

var columns = {
	first: 'First Name',
	last: 'Last Name',
	age: 'Age'
};

In the rest of this tutorial, we’ll use the third form for brevity.

There are often additional configuration options for columns that you’d provide beyond just a label, such as extra CSS classes, column formatters, and so on, which is why you’d often use one of the first two structure definitions instead. Take a look at the “Specifying Grid Columns” section of the Grid documentation for more of those options.

With our grid’s column structure defined, we now need to actually provide some data to display! While more advanced dgrid components like OnDemandGrid support data stores directly, the most basic Grid module simply expects data to be provided as an array of objects passed to the renderArray method:

require([ 'dgrid/Grid', 'dojo/domReady!' ], function (Grid) {
	var data = [
		{ first: 'Bob', last: 'Barker', age: 89 },
		{ first: 'Vanna', last: 'White', age: 55 },
		{ first: 'Pat', last: 'Sajak', age: 65 }
	];

	var grid = new Grid({
		columns: {
			first: 'First Name',
			last: 'Last Name',
			age: 'Age'
		}
	}, 'grid');
	grid.renderArray(data);
});
View Demo

We now have a working grid displaying data from a simple JavaScript data source! Additional data can be appended to the grid by calling renderArray again; to clear the existing data, call grid.refresh().

The basic List and Grid modules only support adding data directly via the renderArray function. If you're interested in using grids with stores, you will want to look at the OnDemandList and OnDemandGrid and Pagination modules, and the Grids and Stores tutorial.

Expanding functionality with mixins and extensions

So far, the grid we’ve created is very bare-bones. dgrid is specifically designed so that you only “pay” for the features you want to use, which means that things like keyboard navigation, row/cell selection, cell editors, and column resizing don’t exist by default and must be requested explicitly when you want to use them.

To do this, simply declare a new grid class using dojo/_base/declare that mixes in all of the desired feature extensions:

require([
	'dojo/_base/declare',
	'dgrid/Grid',
	'dgrid/Keyboard',
	'dgrid/Selection',
	'dojo/domReady!'
], function (declare, Grid, Keyboard, Selection) {
		var data = [
			{ first: 'Bob', last: 'Barker', age: 89 },
			{ first: 'Vanna', last: 'White', age: 55 },
			{ first: 'Pat', last: 'Sajak', age: 65 }
		];

		// Create a new constructor by mixing in the components
		var CustomGrid = declare([ Grid, Keyboard, Selection ]);

		// Now, create an instance of our custom grid which
		// have the features we added!
		var grid = new CustomGrid({
			columns: {
				first: 'First Name',
				last: 'Last Name',
				age: 'Age'
			},
			// for Selection; only select a single row at a time
			selectionMode: 'single',
			// for Keyboard; allow only row-level keyboard navigation
			cellNavigation: false
		}, 'grid');
		grid.renderArray(data);
});
View Demo

See the dgrid documentation for information on available components.

After mixing in Selection and Keyboard, we have a grid which features keyboard navigation and selectable rows. However, we aren’t actually handling anything when users interact with it. Adding event listeners will give us this control.

Handling Events

dgrid uses the dojo/on module introduced in Dojo 1.7 for handling events. Listening for events on a particular grid instance is as simple as calling grid.on, which effectively listens for events received by the grid’s top-level DOM node. Combined with event delegation, this mechanism can be used to easily and efficiently listen for DOM events on any component within the grid, such as individual cells and rows.

In addition to standard DOM events, some dgrid components emit their own custom events. For example, the Selection mixin fires dgrid-select and dgrid-deselect events. Using these, we can begin to look at what’s happening when a user interacts with the grid:

grid.on('dgrid-select', function (event) {
	// Report the item from the selected row to the console.
	console.log('Row selected: ', event.rows[0].data);
});
grid.on('dgrid-deselect', function (event) {
	console.log('Row de-selected: ', event.rows[0].data);
});

Using event delegation, we can also easily listen for native DOM events on various elements within the grid itself:

grid.on('.dgrid-row:click', function (event) {
	var row = grid.row(event);
	console.log('Row clicked:', row.id);
});
View Demo

In order to use event delegation, you must make sure you’ve loaded dojo/query. Making this module optional helps keep the filesize down when you don’t want or need any event delegation.

What now?

So far, this tutorial has given just a glimpse of what dgrid offers. Future dgrid tutorials will explore some of the additional components offered out of the box, such as OnDemandList, which allows you to connect your grid directly to a dstore store. In the meantime, check out the dgrid documentation and let us know if you have any issues!

Resources