Using IndexedDB in your JavaScript/HTML5 Windows 8 Metro Apps

Building Windows 8 Metro Apps using HTML5 standards is, for the most part, a very easy process. One of the HTML5 technologies, which is very powerful but not as well understood, is the IndexedDB technology. While you may be thinking this is just another name for WebSQL (aka SQLite), it is actually something different entirely. IndexedDB is a non-relational data store designed to store JSON objects in collections known as an Object Store within a Database. Each Object Store has a single key, which can be configured to auto increment. Furthermore, the Object Store may also utilize one or more indexes defined on other fields within the object. If you are already familiar with IndexedDB for non Metro based apps, you will feel right at home as the API is unchanged.

To get us started we first need to open/create a DB for our application.

 function openAppDB(success) {
 var request ="MyAppDb", 1);
 // Add asynchronous callback functions
 request.onerror = function () { /* Error */ };
 request.onsuccess = function (evt) { success(; };
 request.onupgradeneeded = function (evt) { upgradeAppDB(evt); };
 request.onblocked = function () { /* Blocked Logic */ };
 function upgradeAppDB(evt) {
 //Perform Upgrade Operations here
 var txn =;
 var objectStore ="objstore1", { keyPath: "id", autoIncrement: true });
 objectStore.createIndex("text1", "text1", { unique: false });
 txn.oncomplete = function () { /* Upgrade Complete */ };

The code may appear a little unusual if you are not used to the asynchronous nature built into the IndexedDB API. This actually serves a very important purpose as it reduces the amount of time the main thread is blocked. Within the openAppDB method, it starts off by calling with the name of the DB and the desired version number. Next we provide a function for the various events, onerror, onsuccess, onupgradeneeded and onblocked. For the sample code, only two of the events are populated. When the database being opened is an older version (or new), the upgradeAppDB method will be called. Within this method we start off by grabbing a reference to the transaction and call createObjectStore to create our first Object Store within the database. Next the method adds a single index on the text1 field. Back to the openAppDB for the onsuccess event. Within the open event, it calls the method passed in at the start. In this instance is another method called AddMethods shown below. This technique of passing callback method is a good technique that helps to provide structure to asynchronous operations such as these.

 function AddRecords(db)
 //Start a transaction
 var txn = db.transaction("objstore1", "readwrite");
 txn.oncomplete = function () { /* Transaction Complete */ };
 txn.onerror = function () { /* Transaction Error */ };
 txn.onabort = function () { /* Transaction Aborted */ };
 //Open the Object Store objstore1
 var objstore = txn.objectStore("objstore1");
 var data = {
 "text1": "Text Value",
 "DateTime": new Date()
 var request = objstore.put(data);
 request.onsuccess = function (e) { /* Changes Committed Successfully*/ }; ;
 request.onerror = function (e) { /* Error */ };

Again, the AddRecords method will be called upon completion of opening the DB. As you can see we start with creating a transaction on one or more Object Stores in either read only or Read/Write. After the transaction event handlers, the code then opens the object store objstore1. Next a simple data object is created with two fields, text1 and DateTime. To add the records to the Object Store the data object is passed to the put method. The put operation is again an asynchronous operation, which includes onsuccess and onerror events. At this point the transaction will then finish and commit all changes to the database. To retrieve records from the database, we will reuse the openAppDB shown above, but pass in another callback method as shown below.

 function ReadRecords(db) {
 var txn = db.transaction("objstore1", "readwrite");
 txn.oncomplete = function () { /* Transaction Complete */ };
 txn.onerror = function () { /* Transaction Error */ };
 txn.onabort = function () { /* Transaction Aborted */ };
 //Open the Object Store objstore1
 var objstore = txn.objectStore("objstore1");
 var index = objstore.index("text1");
 index.get("Text Value").onsuccess = function (evt) {
 var res =;

By using a different call back for the openAppDB, as shown in the first line above, we can reuse any code built to create/upgrade the database and Object Stores as well as initial error handling. Within the ReadRecords method, we create a new transaction for objstore1 with the transaction event handlers. Then we create a reference to the objstore1 for the transaction. We could at this point call the get method on the Object Store with a key value; however, we can go one step further and make use of the index we created previously. By creating a reference to the index we can perform simple searches (exact match) using the get method based upon a non-key field. One downside to this approach is that it will only return a single record, which matches the search phrase provided. To perform more complicated search operations or return additional matching records we will need to use a cursor on the index.


As you can see, the IndexedDB API is a bit different, but not all that difficult. If you have never used a non-relational database before you will need to spend a little bit of time rethinking how you want to store the data and interconnect it. Even with these minor differences to get use too, IndexedDB is a very power database storage mechanism, which will soon be widely used across HTML5 apps.

Related Articles


  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds