Introduction to IndexedDB

Introduction

 
As the name implies, IndexedDB is a database in which we can do all kinds of operations we do in a normal database. This IndexedDB has been introduced with Html. This allows a user to store large amounts of data in their browser. It has been proved that IndexedDB is more powerful and efficient than other storage mechanisms like local storage and session storage. Basically IndexedDB is an API that helps the developers to do some database operations on the client-side, like creating a database, opening the transaction, creating tables, inserting values to tables, deleting values, and reading the data. If you need any other way to save some data on the client-side, you can use storage mechanisms introduced in HTML5. Now we will look at some of the operations a developer can do with IndexedDB. I hope you will like this.
 
Background
 
Before introducing IndexedDB, developers were familiar with Web SQL.
 
Why use IndexedDB instead of Web SQL
 
W3C has announced that the use of Web SQL is obsolete and deprecated, hence it is not recommended to use Web SQL in your applications. Most of the modern web browsers like Mozilla do not support the use of Web SQL, this is also a great limitation of Web SQL.
 
Now we have an alternative to Web SQL, IndexedDB, which more efficient and faster than Web SQL. The following are some of the main advantages of IndexedDB.
  • It stores the data as Key-Pair values
  • It is asynchronous
  • It is non-relational
  • Can access the data from the same domain
Using the code
 
As you all know, the first step to work with a database is just creating it.
 
Create/Open IndexedDB Database
 
It is always better to check whether your browser supports IndexedDB or not. To check that you can use the following syntax:
  1. <script type="text/javascript">  
  2. window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;  
  3. //check whether the database is created or not.  
  4. if (!window.indexedDB)  
  5. {  
  6.     alert("Oops, Does not support IndexedDB");  
  7. }  
  8. </script>  
So if your browser supports IndexedDB, you are ready to go! Cool! Now we can create a database.
  1. //check whether the database is created or not.  
  2. if (!window.indexedDB)  
  3. {  
  4.     alert("Oops, Does not support IndexedDB");  
  5. }  
  6. else  
  7. {  
  8.     //Create database  
  9.     var dbName = 'myDB'// Database name  
  10.     var dbVersion = 2; // Database version  
  11.     var crDB = window.indexedDB.open(dbName, dbVersion);  
  12. }  
Here the first parameter is the database name and the second one is the version of your database. A version represents your database current schema. If everything goes well, you can see your database in your browser resources as follows.
 
IndexedDB Creation
 
IndexedDB Creation
 
When you create a database some certain events are fired, they are:
  • onupgradeneeded
    1. crDB.onupgradeneeded = function (event)  
    2. {  
    3.     alert("That's cool, we are upgrading");  
    4.     db = event.target.result;  
    5.     var objectStore = db.createObjectStore("UserName",  
    6.     {  
    7.         keyPath: "UserID"  
    8.     });  
    9. };  
    This event gets fired when you try upgrading your database. Here we are creating an object store with the name ‘UserName’ and index key ‘UserID’. The following is the output you get when the onupgradeneeded is fired.
     
    IndexedDB onupgradeneeded Alert
     
    IndexedDB onupgradeneeded Alert
     
    IndexedDB onupgradeneeded Output
     
    IndexedDB onupgradeneeded Output
     
  • onsuccess
    1. crDB.onsuccess = function (event) {  
    2.    alert("Awesome, You have successfully Opened a Databse!");  
    3.    db = event.target.result;  
    4. }  
    If there are no errors, you will get an alert as follows.
     
    IndexedDB OnSuccess Alert
     
    IndexedDB OnSuccess Alert 
     
  • onerror
    1. crDB.onerror = function (event) {  
    2.    alert("Oops, There is error!"event);  
    3. }  
    Here crDB is our database instance. Once this is done, we can start using the transaction as we use in SQL.
Creating transaction
 
To create a transaction we can use the following syntax. We can use the transaction method from our database instance.
  1. //Creating transaction  
  2. var myTran = db.transaction(["UserName"], "readwrite");  
  3. myTran.oncomplete = function (e)  
  4. {  
  5.     alert("Awesome, Transaction is successfully created!");  
  6. };  
  7. myTran.onerror = function (e)  
  8. {  
  9.     alert("Oops, There is error!", e.message);  
  10. };  
Here db is our database instance. And myTran is our transaction object which we are going to use for our upcoming operations. We are creating a transaction with read-write permission, that is why we have given property as ‘readwrite’ while creating a transaction. Why we use the transaction is, as you all know transaction can be rollbacked. For example, if any of the operations throws an error, the transaction will be rolled back so there won’t be any kind of mismatching data happening. And of course, we can easily manage error logs with the help of transaction. Shall we write queries needed for our operations?
 
Adding the data
 
Once our transaction is ready we can insert some data to our object in the transaction on success event, which we have called inside of database onsuccess event. Please check the below code.
  1. crDB.onsuccess = function (event)  
  2. {  
  3.     alert("Awesome, You have successfully Opened a Databse!");  
  4.     db = event.target.result;  
  5.     //Creating transaction  
  6.     var myTran = db.transaction(["UserName"], "readwrite");  
  7.     myTran.oncomplete = function (e)  
  8.     {  
  9.         alert("Awesome, Transaction is successfully created!");  
  10.     };  
  11.     myTran.onsuccess = function (e)  
  12.     {  
  13.         alert("Awesome, Transaction is successfully created!");  
  14.         //Adding the data  
  15.         var myObj = myTran.objectStore("UserName");  
  16.         var myNames = ["Sibi""Aji""Ansu""Shantu""Aghil"]; //Array with names  
  17.         for (var i = 0; i < 5; i++)  
  18.         { //Adding 5 objects  
  19.             myObj.add(  
  20.             {  
  21.                 UserID: 'SBKL0' + i,  
  22.                 Name: myNames[i]  
  23.             });  
  24.         }  
  25.     };  
  26.     myTran.onerror = function (e)  
  27.     {  
  28.         alert("Oops, There is error!", e.message);  
  29.     };  
  30. }  
Here myNames is the array in which we have few names and we are using a loop to insert few data to the object. Now you can see that your data have been added to the object in your browser resources.
 
IndexedDB Adding Data To Objects
 
IndexedDB Adding Data To Objects
 
We have successfully added data, right? Now we will see how to remove the data we just added.
 
Removing the data
 
If there is adding, there should be deleting. You can delete an object from object store as follows.
  1. setTimeout(function () {  
  2.    db.transaction(["UserName"], "readwrite").objectStore("UserName").delete('SBKL00');  
  3. }, 10000);  
So you can re write the on success event of transaction as follows.
  1. myTran.onsuccess = function (e)  
  2. {  
  3.     alert("Awesome, Transaction is successfully created!");  
  4.     //Adding the data  
  5.     var myObj = myTran.objectStore("UserName");  
  6.     var myNames = ["Sibi""Aji""Ansu""Shantu""Aghil"]; //Array with names  
  7.     for (var i = 0; i < 5; i++)  
  8.     { //Adding 5 objects  
  9.         myObj.add(  
  10.         {  
  11.             UserID: 'SBKL0' + i,  
  12.             Name: myNames[i]  
  13.         });  
  14.     }  
  15.     setTimeout(function ()  
  16.     {  
  17.         db.transaction(["UserName"], "readwrite").objectStore("UserName").delete('SBKL00');  
  18.     }, 10000);  
  19. };  
It can give you an output as follows.
 
IndexedDB Deleting Data From Objects
 
IndexedDB Deleting Data From Objects
 
Now we will see how to access particular data from the object-store.
 
Access the data with key
 
To access particular data, we will add a button and in the button click event, we will fetch the details needed as a request.
  1. <input id="btnGet" type="button" value="Get Name" />  
Click event is as follows.
  1. $(function ()  
  2. {  
  3.     $('#btnGet').click(function ()  
  4.     {  
  5.         var get = db.transaction(["UserName"], "readwrite").objectStore("UserName").get('SBKL01');  
  6.         get.onsuccess = function (event)  
  7.         {  
  8.             alert("The name you have requested is : " + get.result.Name);  
  9.         };  
  10.     });  
  11. });  
You can get the alert as follows, if you run your code.
 
IndexedDB Get The Data With Key
 
IndexedDB Get The Data With Key
 
Now we will see how we can update data with the Get method.
 
Updating the data
 
To update the data we will have a button and in the button click, we will fire the needed code.
  1. <input id="btnUpdate" type="button" value="Update Name" />  
And click event is as follows.
  1. $('#btnUpdate').click(function ()  
  2. {  
  3.     var updObject = db.transaction(["UserName"], "readwrite").objectStore("UserName");  
  4.     var upd = updObject.get('SBKL03');  
  5.     upd.onsuccess = function (event)  
  6.     {  
  7.         upd.result.Name = 'New Name';  
  8.         updObject.put(upd.result);  
  9.     };  
  10. });  
Here we are getting an element using the get method, and we are updating the value in the result, once it is done, we will assign that new result to the object store using put method.
 
It will give you an output as follows.
 
IndexedDB Update The Data With Key
 
IndexedDB Update The Data With Key
 
Another interesting thing is, we can use cursors also as we use in SQL if we need to loop through some data. Here I will show you how we can do that.
 
Using Cursor
 
Create a button and write a few lines of code as follows.
  1. <input id="btnShow" type="button" value="Show the data" />  
Then we will create an HTML table.
  1. <div id="myTab">  
  2.     <table id="show">  
  3.         <thead>  
  4.             <th>User ID </th>  
  5.             <th>Name</th>  
  6.         </thead>  
  7.         <tbody></tbody>  
  8.     </table>  
  9. </div>  
Now we can write the cursor as follows.
  1. $('#btnShow').click(function ()  
  2. {  
  3.     var curObject = db.transaction(["UserName"], "readwrite").objectStore("UserName");  
  4.     curObject.openCursor().onsuccess = function (event)  
  5.     { //Opening the cursor  
  6.         var cur = event.target.result;  
  7.         if (cur)  
  8.         { // Checks for the cursor  
  9.             $('#show').append('<tr><td>' + cur.key + '</td><td>' + cur.value.Name + '</td></tr>');  
  10.             cur.continue();  
  11.         }  
  12.     };  
  13.     $('#myTab').show();  
  14. });  
Here we are creating a cursor using the function openCursor() and in the onsuccess event we are looping through the cursor. You can always give some styles to your table.
  1. <style>  
  2.     table,  
  3.     tr,  
  4.     td,  
  5.     th {  
  6.         border: 1px solid #ccc;  
  7.         border-radius: 5px;  
  8.         padding: 10px;  
  9.         margin: 10px;  
  10.     }  
  11. </style>  
That is all. Now when you click the show button, you can see the data in a table format as follows.
 
IndexedDB Using Cursor
 
IndexedDB Using Cursor
 
Complete code
  1. <!DOCTYPE html>  
  2. <html>  
  3.   
  4.     <head>  
  5.         <title>Introduction to IndexedDB</title>  
  6.         <script src="Scripts/jquery-1.11.1.min.js"></script>  
  7.         <script type="text/javascript">  
  8.         var dbName = 'myDB'; // Database name  
  9.         var dbVersion = 2; // Database version  
  10.         var crDB;  
  11.         var db;  
  12.         window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;  
  13.         //check whether the database is created or not.  
  14.         if (!window.indexedDB)  
  15.         {  
  16.             alert("Oops, Does not support IndexedDB");  
  17.         }  
  18.         else  
  19.         {  
  20.             //Create database  
  21.             crDB = window.indexedDB.open(dbName, dbVersion);  
  22.             var db;  
  23.             crDB.onerror = function (event)  
  24.             {  
  25.                 alert("Oops, There is error!", event);  
  26.             }  
  27.             crDB.onupgradeneeded = function (event)  
  28.             {  
  29.                 alert("That's cool, we are upgrading");  
  30.                 db = event.target.result;  
  31.                 var objectStore = db.createObjectStore("UserName",  
  32.                 {  
  33.                     keyPath: "UserID"  
  34.                 });  
  35.             };  
  36.             crDB.onsuccess = function (event)  
  37.             {  
  38.                 alert("Awesome, You have successfully Opened a Databse!");  
  39.                 db = event.target.result;  
  40.                 //Creating transaction  
  41.                 var myTran = db.transaction(["UserName"], "readwrite");  
  42.                 myTran.oncomplete = function (e)  
  43.                 {  
  44.                     alert("Awesome, Transaction is successfully created!");  
  45.                 };  
  46.                 myTran.onsuccess = function (e)  
  47.                 {  
  48.                     alert("Awesome, Transaction is successfully created!");  
  49.                     //Adding the data  
  50.                     var myObj = myTran.objectStore("UserName");  
  51.                     var myNames = ["Sibi""Aji""Ansu""Shantu""Aghil"]; //Array with names  
  52.                     for (var i = 0; i < 5; i++)  
  53.                     { //Adding 5 objects  
  54.                         myObj.add(  
  55.                         {  
  56.                             UserID: 'SBKL0' + i,  
  57.                             Name: myNames[i]  
  58.                         });  
  59.                     }  
  60.                     setTimeout(function ()  
  61.                     {  
  62.                         db.transaction(["UserName"], "readwrite").objectStore("UserName").delete('SBKL00');  
  63.                     }, 10000);  
  64.                 };  
  65.                 myTran.onerror = function (e)  
  66.                 {  
  67.                     alert("Oops, There is error!", e.message);  
  68.                 };  
  69.             }  
  70.         }  
  71.         $(function ()  
  72.         {  
  73.             $('#myTab').hide();  
  74.             $('#btnGet').click(function ()  
  75.             {  
  76.                 var get = db.transaction(["UserName"], "readwrite").objectStore("UserName").get('SBKL01');  
  77.                 get.onsuccess = function (event)  
  78.                 {  
  79.                     alert("The name you have requested is : " + get.result.Name);  
  80.                 };  
  81.             });  
  82.             $('#btnUpdate').click(function ()  
  83.             {  
  84.                 var updObject = db.transaction(["UserName"], "readwrite").objectStore("UserName");  
  85.                 var upd = updObject.get('SBKL03');  
  86.                 upd.onsuccess = function (event)  
  87.                 {  
  88.                     upd.result.Name = 'New Name';  
  89.                     updObject.put(upd.result);  
  90.                 };  
  91.             });  
  92.             $('#btnShow').click(function ()  
  93.             {  
  94.                 var curObject = db.transaction(["UserName"], "readwrite").objectStore("UserName");  
  95.                 curObject.openCursor().onsuccess = function (event)  
  96.                 { //Opening the cursor  
  97.                     var cur = event.target.result;  
  98.                     if (cur)  
  99.                     { // Checks for the cursor  
  100.                         $('#show').append('<tr><td>' + cur.key + '</td><td>' + cur.value.Name + '</td></tr>');  
  101.                         cur.continue();  
  102.                     }  
  103.                 };  
  104.                 $('#myTab').show();  
  105.             });  
  106.         });  
  107.         </script>  
  108.         <style>  
  109.         table,  
  110.         tr,  
  111.         td,  
  112.         th {  
  113.             border1px solid #ccc;  
  114.             border-radius: 5px;  
  115.             padding10px;  
  116.             margin10px;  
  117.         }  
  118.         </style>  
  119.     </head>  
  120.   
  121.     <body> <input id="btnGet" type="button" value="Get Name" /> <input id="btnUpdate" type="button" value="Update Name" /> <input id="btnShow" type="button" value="Show the data" />  
  122.         <div id="myTab">  
  123.             <table id="show">  
  124.                 <thead>  
  125.                     <th>User ID </th>  
  126.                     <th>Name</th>  
  127.                 </thead>  
  128.                 <tbody></tbody>  
  129.             </table>  
  130.         </div>  
  131.     </body>  
  132.   
  133. </html>  
That is all. We did it. Have a happy coding.
 

Conclusion

 
Did I miss anything that you may think is needed? Did you try Web SQL yet? Have you ever wanted to do this requirement? Did you find this post useful? I hope you liked this article. Please share your valuable suggestions and feedback.
 
Want to learn more about IndexedDB, contrinue here: HTML 5 IndexedDB Database 
 
Your turn. What do you think?
 
A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, Asp.Net Forum instead of commenting here. Tweet or email me a link to your question there and I’ll definitely try to help if I can.