Telerik blogs

See the basics of IndexedDB—create a database, add data, retrieve data and delete data—and advanced topics such as indexing, transactions and versioning.

In this age of modern web apps, web developers need to be able to store data on a client’s browser. This improves speed, lets you use the app when you’re not connected to the internet and gives you a more personalized experience. By doing this, we go from having a simple web page to having an interactive app where data is pulled from the server and saved and changed on the user’s device.

IndexedDB, a low-level API for storing large amounts of structured data on the client side, is one of the technologies that make this shift possible. IndexedDB is a way to store more significant amounts of data securely and reliably in the user’s browser.

In this beginner’s guide, we will explore the basics of IndexedDB, including how to create a database, add data, retrieve data and delete data. We will also cover advanced topics such as indexing, transactions and versioning. By the end of this guide, you will have a solid understanding of how to use IndexedDB to build powerful client-side web applications that can work offline.

Understanding IndexedDB

IndexedDB is a client-side storage mechanism for web applications that allows developers to store large amounts of data locally. It is a JavaScript-based object-oriented database that enables developers to store, retrieve and manipulate data in a structured way. IndexedDB is supported by all modern web browsers, making it an excellent choice for building offline web applications.

IndexedDB is a client-side storage mechanism that allows developers to store data in a structured format, similar to a database. Unlike cookies or local storage, IndexedDB can store large amounts of data and can be queried using indexes.

IndexedDB is a key-value store, storing data as objects with keys and values. Each object in IndexedDB has a unique key, which can be used to retrieve the object later. The keys can be any data type, including strings, numbers and dates.

Why Use IndexedDB?

IndexedDB is a powerful tool for web developers, as it allows them to store large amounts of data on the client-side. This can be useful for web applications that need to work offline or need to store data that is too sensitive to store on a remote server.

One of the best things about IndexedDB is that it works with many different browsers. It works with all big web browsers, like Chrome, Firefox, Safari and Edge. This means you can use IndexedDB to build your web application and ensure it will work the same way in all browsers, giving users a consistent experience.

Another good reason to use IndexedDB is that it can be used offline. IndexedDB is different from other web storage systems because it lets you view and change data even when the user is not online. This offline feature is essential for apps that need to work without an internet connection, like mobile apps or web apps that need to share data with a server.

IndexedDB also allows developers to perform complex queries on the data, using indexes. This can be useful for applications that need to search through large amounts of data quickly.

Overall, IndexedDB is a powerful tool for web developers who need to store large amounts of data on the client-side. By using IndexedDB, developers can create web applications that are fast, responsive and work offline.

Getting Started with IndexedDB

To start using IndexedDB, we need to set it up first. In this section, we will cover how to create a database and upgrade it.

let request = window.indexedDB.open("guide_to_indexeddb_database", 3);

If the database does not exist, it will be created automatically. Otherwise, the open() method will check the version of the database. You can use the IDBOpenDBRequest object returned by the open() method to manage success, error and upgrade events. It is essential to note that the open() method is asynchronous, meaning it does not impede the execution of other code while it performs its function.

Once we have opened a connection to the database, we can create object stores. An object store is where we store our data. We can create an object store using the createObjectStore() method.

let store = db.createObjectStore('my_first_store', { keyPath: 'id' });

In this example, we created an object store called my_first_store with a key path of id. The keyPath is the property that uniquely identifies each record in the object store.

Upgrading a Database

Upgrading a database is necessary when we need to change its structure. For example, we might need to add or remove object stores or indexes.

To upgrade a database, we need to listen to the onupgradeneeded event. This event is triggered when the version of the database is lower than the one we provided in the open() method.

request.onupgradeneeded = function(event) {
  let db = event.target.result;

  // Upgrade the database here
};

Inside the onupgradeneeded event, we can create or delete object stores and indexes using the same methods as when creating a database.

let store = db.createObjectStore('my_first_store', { keyPath: 'id' });
let index = store.createIndex('nameIndex', 'name', { unique: false });

In this example, we created an object store called myObjectStore and an index called nameIndex on the name property.

Async IndexedDB

We will not continue to use vanilla JavaScript now to work with IndexedDB. In fact, we will use something much better to increase our productivity and make our code easier to read and our app performance faster.

idb, a library created by Jake Archibald, is a promise-based abstraction layer around IndexedDB. While the raw IndexedDB API provided by JavaScript is powerful, it’s also often seen as complicated and unwieldy due to its callback-based asynchronous model and verbose syntax.

To get started with idb, all we need to do is install it using our package manager:

npm install idb

Or we can use it directly on the browser via jsdelivr:

<script type="module">
  import { openDB, deleteDB, wrap, unwrap } from 'https://cdn.jsdelivr.net/npm/idb@7/+esm';
    
  async function doDatabaseStuff() {
    const db = await openDB();
  }
</script>

idb makes it so much easier for us to work with IndexedDB. Using idb, we can use the new async/await feature of browsers. Now that we have set up idb, let’s create our first database and put some data into it.

We’re going to import idb and create our database:

import { openDB, deleteDB, wrap, unwrap } from "https://cdn.jsdelivr.net/npm/idb@7/+esm";
    
async function doDatabaseStuff() {
  // Create our database.
  const db = await openDB("guide_to_indexeddb_database", 1, {
    upgrade(db) {
      // Create a store of objects
      const store = db.createObjectStore("my_first_store", {
        // The 'id' property of the object will be the key.
        keyPath: "id",
        // If it isn't explicitly set, create a value by auto incrementing.
        autoIncrement: true
      });
    }
  });
}

Now, we’re going to create our transaction and reference our store. After that, we will add our first data object to our database.

import { openDB, deleteDB, wrap, unwrap } from "https://cdn.jsdelivr.net/npm/idb@7/+esm";
    
async function doDatabaseStuff() {
  // Create our database.
  const db = await openDB("guide_to_indexeddb_database", 1, {
    upgrade(db) {
      // Create a store of objects
      const store = db.createObjectStore("my_first_store", {
        // The 'id' property of the object will be the key.
        keyPath: "id",
       // If it isn't explicitly set, create a value by auto incrementing.
        autoIncrement: true
      });
    }
  });
    
  const tx = db.transaction("my_first_store", "readwrite");
  const store = tx.store;
    
  // Create our user object.
  const user = { firstName: "Leonardo", lastName: "Maldonado", age: 25 }; }

We’re going to add our user to our database using a single line, like this:

import { openDB, deleteDB, wrap, unwrap } from "https://cdn.jsdelivr.net/npm/idb@7/+esm";
    
async function doDatabaseStuff() {
  // Create our database.
  const db = await openDB("guide_to_indexeddb_database", 1, {
    upgrade(db) {
      // Create a store of objects
      const store = db.createObjectStore("my_first_store", {
        // The 'id' property of the object will be the key.
        keyPath: "id",
        // If it isn't explicitly set, create a value by auto incrementing.
        autoIncrement: true
      });
    }
  });
  const tx = db.transaction("my_first_store", "readwrite");
  const store = tx.store;
  // Create our user object.
  const user = { firstName: "Leonardo", lastName: "Maldonado", age: 25 };
  // Add our user to the store.
  await Promise.all([tx.store.add(user), tx.done]);
}

Let’s check if it worked successfully. Open our DevTools, go to Application, and under IndexedDB should be the database we just created. If you click on the database name, you can see the store and the user we added.

Working with IndexedDB provides a flexible and powerful way to store and retrieve data on the client side. Whether we need to create, retrieve, update or delete data, IndexedDB offers comprehensive methods and features to handle these operations efficiently.

Conclusion

With this guide, you have a solid foundation for working with IndexedDB. Whether storing user data, caching resources or building complex web applications, IndexedDB can be a valuable tool in your development arsenal. Happy coding!


Leonardo Maldonado
About the Author

Leonardo Maldonado

Leonardo is a full-stack developer, working with everything React-related, and loves to write about React and GraphQL to help developers. He also created the 33 JavaScript Concepts.

Related Posts

Comments

Comments are disabled in preview mode.