FAQ: How can I create a JSONP service-based store?

By on July 9, 2014 11:16 am

DojoFAQ

Dojo’s store API is a common interface for providing data to user interface widgets, such as dgrid, Dijit Select, and Dojo Charting. The beauty of having a consistent API is that once you’ve defined an interface for a data source, that data becomes easily available to all widgets that support the store API. We’re going to look at how you can create a basic, read-only dojo/store API-compliant module for accessing GitHub’s API (specifically, GitHub issues), an example of implementing your own Dojo store.

Implementing basic store methods

For starters, we don’t have to implement all store methods – each method is optional. For a read-only store the most important methods are get and query. These methods enable basic read access to the data: get to retrieve an item by its id, and query to retrieve a set of items that match user-specified criteria. Let’s start with the basic framework and the get method.

  • GitHub’s API URL: https://api.github.com/
  • The API URL for dgrid issues: https://api.github.com/repos/SitePen/dgrid/issues
  • The identity property for a GitHub issue: each issue has an “id” property, but they also have a “number” property – the number is the value displayed in the GitHub UI, and the value that must be provided to the API when requesting a specific issue, so we will use the “number” property as the idProperty in our store
  • Dojo’s dojo/request/script module provides a convenient API for JSONP requests

With this information we can begin our implementation:

define([
	'dojo/_base/declare',
	'dojo/_base/lang',
	'dojo/request/script',
	'dojo/store/util/QueryResults'
], function (declare, lang, request, QueryResults) {
	return declare(null, {
		target: '',
		idProperty: 'number',

		constructor: function (options) {
			lang.mixin(this, options);
		},

		get: function (id) {
			return request(this.target + '/' + id, {
				jsonp: 'callback'
			}).then(function (result) {
				// The information we want is on the 'data'
				// property of the returned results
				return result.data;
			});
		}
	});
});

This short module is enough to begin making GitHub API requests using the Dojo store API:

var dgridIssueStore = new GitHubStore({
	target: 'https://api.github.com/repos/SitePen/dgrid/issues'
});

// Get the JSON data for issue 840
dgridIssueStore.get(840);

What’s a store without a query method?

The ability to query a store is very important, so we have more to do. A basic query method can be implemented very simply:

query: function (query, queryOptions) {
	var resultPromise = request(this.target, {
		query: query,
		jsonp: 'callback'
	}).then(function (result) {
		// The information we want is on the 'data'
		// property of the returned results
		return result.data;
	});

	// QueryResults will add the 'total' property
	// as well as iteration methods
	return QueryResults(resultPromise);
}

Let’s examine how this works:

  • Line 2: Make the JSONP request, adding any query options to the query string of the request URL (valid options for GitHub issues)
  • Line 5: The data value returned should be an array of data, but the GitHub API provides an object with the array stored in the object’s data property, so we have to return a promise that resolves to the array in the data property (line 8).
  • Line 13: The dojo/store API requires that the object returned by the query method have iteration methods (forEach, filter, map) and a total property. The dojo/store/util/QueryResults module is a utility module to add these.

Let’s implement the getIdentity method to have a fairly robust read-only store:

getIdentity: function (object) {
	return object[this.idProperty];
}

That’s it! This store is ready to query GitHub and provide data for a store-backed user interface widget. Here is the store in action with dgrid to render the data:

Production-ready stores

While the store API at its core is pretty simple, the data service API can complicate things, and in this case it does. GitHub’s API does not quite allow arbitrary page sizes, which is part of why we have omitted support for queryOptions (which allows specification of sort, start, and count options) in the query method. You might also want to implement authentication. Server-backed stores are generally dependent on the server for correct paging, sorting, and querying. For GitHub these query options are available. If the data set is small enough, you can load it all client-side and forego your own store implementation – just use dojo/store/Memory.

Learning more

We cover dojo/store, dgrid, dojo/request, advanced store creation, and more in depth in our Dojo workshops offered throughout the US, Canada, and Europe, or at your location. We also provide expert JavaScript and Dojo support and development services, to help you get the most from JavaScript and Dojo.