DEV Community

an-object-is-a
an-object-is-a

Posted on

Local Database and Chrome Extensions (IndexedDB)

Use a local database and Chrome Extension together to increase your app's capacity..


This tutorial assumes you know how Google Chrome Extensions work. Learn more here.

How to make a Chrome Extension in-depth course? Try our Teachable

We have a course for completely-new-to-web-dev'rs and for experienced web dev's who want a more curated experience.

Chrome Extensions and Local Database

To demonstrate IndexedDB in the context of a Chrome Extension, we're going to use a simple HTML page with 2 forms.

  • One form for adding records.
  • One form for searching and editing records.

We'll use this form through the pop-up page of our Chrome Extension.

Let’s begin…

Our manifest file…

// manifest.json
{
    "name": "chrome ext with localDB",
    "description": "chrome ext interacting with IndexedDB",
    "version": "0.1.0",
    "manifest_version": 2,
    "icons": {
        "16": "./obj-16x16.png",
        "32": "./obj-32x32.png",
        "48": "./obj-48x48.png",
        "128": "./obj-128x128.png"
    },
    "background": {
        "scripts": [
            "./background.js"
        ]
    },
    "options_page": "./options.html",
    "browser_action": {
        "default_popup": "popup.html"
    },
    "permissions": []
}
Enter fullscreen mode Exit fullscreen mode

Note:
We don't need any special permissions; we don't need the storage permission to use IndexedDB.


Let's take a look at that background script!

When our Chrome Extension first installs, we create a database…

// background.js
let db = null;

function create_database() {
    const request = window.indexedDB.open('MyTestDB');

    request.onerror = function (event) {
        console.log("Problem opening DB.");
    }

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

        let objectStore = db.createObjectStore('roster', {
            keyPath: 'email'
        });

        objectStore.transaction.oncomplete = function (event) {
            console.log("ObjectStore Created.");
        }
    }

    request.onsuccess = function (event) {
        db = event.target.result;
        console.log("DB OPENED.");
        insert_records(roster);

        db.onerror = function (event) {
            console.log("FAILED TO OPEN DB.")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

…then populate that database.

// background.js
function insert_records(records) {
    if (db) {
        const insert_transaction = db.transaction("roster", "readwrite");
        const objectStore = insert_transaction.objectStore("roster");

        return new Promise((resolve, reject) => {
            insert_transaction.oncomplete = function () {
                console.log("ALL INSERT TRANSACTIONS COMPLETE.");
                resolve(true);
            }

            insert_transaction.onerror = function () {
                console.log("PROBLEM INSERTING RECORDS.")
                resolve(false);
            }

            records.forEach(person => {
                let request = objectStore.add(person);

                request.onsuccess = function () {
                    console.log("Added: ", person);
                }
            });
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

When we get messages to add, get, update, or delete from the foreground..

// background.js
function get_record(email) {
    if (db) {
        const get_transaction = db.transaction("roster", "readonly");
        const objectStore = get_transaction.objectStore("roster");

        return new Promise((resolve, reject) => {
            get_transaction.oncomplete = function () {
            console.log("ALL GET TRANSACTIONS COMPLETE.");
            }

            get_transaction.onerror = function () {
            console.log("PROBLEM GETTING RECORDS.")
            }

            let request = objectStore.get(email);

            request.onsuccess = function (event) {
            resolve(event.target.result);
            }
        });
    }
}

function update_record(record) {
    if (db) {
        const put_transaction = db.transaction("roster", "readwrite");
        const objectStore = put_transaction.objectStore("roster");

        return new Promise((resolve, reject) => {
            put_transaction.oncomplete = function () {
                console.log("ALL PUT TRANSACTIONS COMPLETE.");
                resolve(true);
            }

            put_transaction.onerror = function () {
                console.log("PROBLEM UPDATING RECORDS.")
                resolve(false);
            }

            objectStore.put(record);
        });
    }
}

function delete_record(email) {
    if (db) {
        const delete_transaction = db.transaction("roster", 
        "readwrite");
        const objectStore = delete_transaction.objectStore("roster");

        return new Promise((resolve, reject) => {
            delete_transaction.oncomplete = function () {
                console.log("ALL DELETE TRANSACTIONS COMPLETE.");
                resolve(true);
            }

            delete_transaction.onerror = function () {
                console.log("PROBLEM DELETE RECORDS.")
                resolve(false);
            }

            objectStore.delete(email);
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

…we can respond with getting, updating, and deleting records…


Let's take a look at the pop-up page and its accompanying script.

The popup page is a basic html page. Two forms with buttons…

…and of course our popup-script.js attached so we can capture and manipulate the DOM.

It's in the popup-script.js that we capture form information and send messages to the background script, so the background script can execute
all of the IndexedDB commands…

…and once we receive the IndexedDB data from our background, we go ahead and show the user some visual feedback on the HTML popup page!


If you want a more in-depth guide, check out my full video tutorial on YouTube, An Object Is A.

Using A Local Database(IndexedDB) with A Google Chrome Extension

Latest comments (1)

Collapse
 
vp5h profile image
Pravesh Vyas

This is outdated. Ideally people should use MV3 and use offscreen thing. Even I am researching about it.