It’s been some time since dojox/storage, and a lot of things changed since then. Most notably: Browsers now have IndexedDB, and Dojo now has the dojo/store API that widgets can directly work with.
The dojo/store API was built with IndexedDB and offline in mind, has a nice API and allows asynchronism, meaning that it can return Promises instead of values. The only thing missing was a persistence layer that would take data via that API and store it in the user’s browser, e.g. for offline availability.
And that’s what Storehouse is: A persistent object store implementing the dojo/store API.
How it works
Storehouse is built upon dojo/store/Memory, so you have all the API you have with the Memory store, just that the data gets persisted client-side.
Storehouse keeps a copy of the stored data in memory, allowing for fast, synchronous read access and queries.
Only write operations are asynchronous (as the underlying engine might work asynchronously itself), and return Promises to make working with it as easy as possible. For more information on Promises, please refer to the Dojo documentation.
Download the Storehouse package and place it somewhere in your app’s directories, e.g. next to the dojo folder.
Adding Storehouse to your app
Storehouse comes as an AMD module, so it can be easily required, but we need to tell dojo where to find it. To do so, we use the
dojoConfig configuration object:
You can then require it in your app:
The Storehouse constructor takes an object as only argument that is used for configuration. In addition to the
storeId property, which is used to identify the store, there is an optional
idProperty property: You can use that to define which property on the objects you are going to store should be used to identify them. By default, this is set to
id. However, for different types of objects, it can be useful to set this to something else. An example: If you want to store customer data, and the customer objects have a
customerId property that is unique to each customer, you could use this to identify the objects:
Now, Storehouse will work with the
customerId property to identify objects.
Before we can do data operations, we first must open the Storehouse instance. The
open() call returns a Promise:
Reading data works in a synchronous fashion, just like with dojo/store/Memory. To obtain an object from the store, call the
get() method and provide the object’s id as argument:
To run a query against the store, call the
query() method and pass a query object argument:
For querying, Storehouse uses dojo’s
simpleQueryEngine. For more details on querying, please refer to the tutorial about Dojo Object Stores.
Writing data works in an asynchronous fashion. Methods that write data are
remove(). Those methods return a promise. Storing a data object looks like this:
Same goes for removal:
An example of CRUD operations can be found here: http://jensarps.github.io/storehouse/example/basic/.
The source code of the example can be found here: https://github.com/jensarps/storehouse/tree/master/example/basic.
Using Storehouse as data store for Widgets
Widgets that connect to the dojo/store API – i.e. widgets that have a dojo store as data backend – work with Storehouse out of the box. Just pass an opened Storehouse instance as store to the widget, just like you would do with a Memory store:
That’s it – everything that is added to the store is now persisted and available to the widget.
An example of using Storehouse as store for a ComboBox widget can be found here: http://jensarps.github.io/storehouse/example/widget/.
The source code of the example can be found here: https://github.com/jensarps/storehouse/tree/master/example/widget.
Setting Engine Preference
Storehouse has a configurable engine preference; be default, the order of preference is: IndexedDB, localStorage, Cookie. This, however can be changed. If you want Storehouse to prefer localStorage as backend over IndexedDB, you can tell it so in the constructor:
'cookie' from the list:
As you can see, the names in the
enginePreference Array are all lower-case.