Rendering All Store Data at Once

As of dgrid 1.1.0, the mixin from this tutorial is now available as dgrid/extensions/SingleQuery, including additional features such as loadingMessage and noDataMessage support.

The Using Grids and Stores Tutorial discussed dgrid's OnDemandList and Pagination components, which read data from dstore stores. OnDemandList fetches pages of data as the user scrolls, and Pagination displays one page of data at a time.

However, there are cases where you might not want paging functionality. For example, perhaps you have a small in-memory store, and are interested in re-styling the grid so that its height is determined by the store's full contents. In this case, the scroll-based rendering of OnDemandList would be irrelevant, and the paging style of Pagination would be undesirable.

For such cases, it is trivial to create a mixin which issues a single range-less query to the store and renders the results all at once.

Note: This mixin should only be used with limited sets of data, preferably from in-memory stores, in order to maintain reasonable performance.

Querying and Rendering All Store Items

Let's create a mixin that extends the refresh method to perform a range-less query:

define([
	'dojo/_base/declare',
	'dgrid/_StoreMixin'
], function (declare, _StoreMixin) {
	return declare(_StoreMixin, {
		// summary:
		//		dgrid mixin which implements the refresh method to
		//		always perform a single query with no start or count
		//		specified, to retrieve all relevant results at once.
		//		Appropriate for grids using memory stores with small
		//		result set sizes.

		refresh: function () {
			var self = this;

			// First defer to List#refresh to clear the grid's
			// previous content
			this.inherited(arguments);

			if (!this._renderedCollection) {
				return;
			}

			return this._trackError(function () {
				var queryResults = self._renderedCollection.fetch();
				queryResults.totalLength.then(function (total) {
					// Record total so it can be retrieved later via get('total')
					self._total = total;
				});
				return self.renderQueryResults(queryResults);
			});
		},

		renderArray: function () {
			var rows = this.inherited(arguments);

			// Clear _lastCollection which is ordinarily only used for
			// store-less grids
			this._lastCollection = null;

			return rows;
		}
	});
});
View Demo

You can double-click the mixin code above to select all of it for easy copying.

The code above overrides List#refresh to call _StoreMixin#renderQueryResults, which handles fetching and rendering the data. Filtering and sort still work as expected, as seen in the demo. This is thanks to the _setCollection and _applySort methods defined in _StoreMixin, which this mixin inherits. OnDemandList and Pagination also inherit _StoreMixin, and it is intended to serve as a baseline for any customized logic involving store interaction.

Another _StoreMixin feature used above is the _trackError method, which can be used to wrap store calls. Errors which occur in calls wrapped by _trackError are emitted via dgrid-error events, making it possible to react to problems which occur as a result of operations initiated by dgrid.

Automatically Adjusting Grid Height

As mentioned earlier, one particularly useful scenario for this type of mixin is when there is a desire to show all of the data at once, where the grid's height is determined by its contents. This can be accomplished simply by adding the dgrid-autoheight class to an instance:

	var grid = new (declare([ Grid, SingleQuery ]))({
		className: 'dgrid-autoheight',
		...
	});
View Demo

Conclusion

The above examples should provide a good starting point for use cases which involve rendering the entirety of a store's data at once. While this isn't appropriate in every application, the situation presents itself often enough that it makes sense to standardize this pattern.

Resources