Search code examples
indexeddbdexie

IndexedDB as a backend for a data-table web component


I am working on a data-table/grid web component that supports sorting, filtering, infinite scrolling etc. I am looking into replacing my existing data model with IndexedDB (using Dexie).

My initial plan was to use a single db and have a "table" for each component. However, after reading up on the documentation, I realised that every time a new table is added, the version of the db will go up.

What does that imply?

  • Do I need to keep a track of this version number?
  • If a grid is using the db and another grid upgrades the db, will the data be lost?
  • Is it better to use a DB per component instead?

Thanks for any help


Solution

  • It's true that indexedDB's schema is rather static. Whenever you must change it, it will need to close down all existing connections which may interupt other tabs with your app loaded. If all instances of your app behaves the same - that is close and reopen its database dynamically whenever an 'versionchange' event occurs. This would be possible. However, long running transactions will block it from upgrading until they are done.

    I'm curious about what you are trying to accomplish. I suppose you want to utilize indexedDB indexes for sorting and paging/scrolling. But it is not clear if you have a concrete model or if your component is going to be generic / adapt to any model /schema.

    If your model is concrete, and your components are specific for an end-user app. You could model that statically using Dexie (db.version(1).stores(...)). But as you put this question, I suppose you want to create a generic component, the question is whether you really should define a schema within your component or rather let the user of it define that and letting your component adapt to existing databases instead. For example, the user of your component may want to define the database and use your component as a data viewer. Your component could take input arguments as such:

    (databaseName, tableName, columns)
    

    You can then instanciate a Dexie without specifying schema and instead just open an existing database:

    var db = new Dexie(databaseName);
    // Don't specify version() - open dynamically!
    db.open().then(db => {
        var table = db.table(tableName);
        var indexedColumns = table.schema.indexes.map(idx => idx.keyPath);
        if (table.schema.primKey.keyPath)
            indexedColumns.unshift(table.schema.primKey.keyPath);
        }
        // Here you can render your columns.
        // For each column that also exists in indexedColumns, you can
        // orderBy() or put queries based on it.
    });
    

    Related docs: