A simple key-value Storage module for Ionic apps. This utility uses the best storage engine available on the platform without having to interact with it directly (some configuration required, see docs below).
As of 3.x, this library now supports any JavaScript project (old versions only supported Angular), and Angular-specific functionality has been moved to a new @ionic/storage-angular
package.
Out of the box, Ionic Storage will use IndexedDB
and localstorage
where available. To use SQLite for native storage, see the SQLite Installation instructions.
For teams building security sensitive applications requiring encryption, 3.x now supports encryption through Ionic Secure Storage, see Encryption Support for instructions on using it.
npm install @ionic/storage
If using Angular, install the @ionic/storage-angular
library instead:
npm install @ionic/storage-angular
If you'd like to use SQLite as a storage engine, see the SQLite Installation instructions.
import { Storage } from '@ionic/storage';
const store = new Storage();
await store.create();
See the Usage - API section below for an overview of the supported methods on the storage instance.
Usage in Angular using Services and Dependency Injection requires importing the IonicStorageModule
and then injecting the Storage
class.
First, edit your NgModule declaration in src/app/app.module.ts
or in the module for the component you'll use the storage library in, and add IonicStorageModule
as an import:
import { IonicStorageModule } from '@ionic/storage-angular';
@NgModule({
imports: [
IonicStorageModule.forRoot()
]
})
export class AppModule { }
Next, inject Storage
into a component. Note: this approach is meant for usage in a single component (such as AppComponent
). In this case, create()
should only be called once. For use in multiple components, we recommend creating a service (see next example).
import { Component } from '@angular/core';
import { Storage } from '@ionic/storage-angular';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(private storage: Storage) {
}
async ngOnInit() {
// If using a custom driver:
// await this.storage.defineDriver(MyCustomDriver)
await this.storage.create();
}
}
For more sophisticated usage, an Angular Service should be created to manage all database operations in your app and constrain all configuration and database initialization to a single location. When doing this, don't forget to register this service in a providers
array in your NgModule
if not using providedIn: 'root'
, and ensure that the IonicStorageModule
has been initialized in that NgModule
as shown above. Here's an example of what this service might look like:
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage-angular';
@Injectable({
providedIn: 'root'
})
export class StorageService {
private _storage: Storage | null = null;
constructor(private storage: Storage) {
this.init();
}
async init() {
// If using, define drivers here: await this.storage.defineDriver(/*...*/);
const storage = await this.storage.create();
this._storage = storage;
}
// Create and expose methods that users of this service can
// call, for example:
public set(key: string, value: any) {
this._storage?.set(key, value);
}
}
Then, inject the StorageService
into your pages and other components that need to interface with the Storage engine.
The Storage API provides ways to set, get, and remove a value associated with a key, along with clearing the database, accessing the stored keys and their quantity, and enumerating the values in the database.
To set an item, use set(key, value)
:
await storage.set('name', 'Mr. Ionitron');
To get the item back, use get(name)
:
const name = await storage.get('name');
To remove an item:
await storage.remove(key);
To clear all items:
await storage.clear();
To get all keys stored:
await storage.keys()
To get the quantity of key/value pairs stored:
await storage.length()
To enumerate the stored key/value pairs:
storage.forEach((key, value, index) => {
});
To enable encryption when using the Ionic Secure Storage driver:
storage.setEncryptionKey('mykey');
See Encryption Support below for more information.
The Storage engine can be configured both with specific storage engine priorities, or custom configuration options to pass to localForage. See the localForage config docs for possible options: https://github.com/localForage/localForage#configuration
Pass configuration options in the Storage
constructor:
const storage = new Storage({
name: '__mydb',
driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
});
import { Drivers, Storage } from '@ionic/storage';
import { IonicStorageModule } from '@ionic/storage-angular';
@NgModule({
//...
imports: [
IonicStorageModule.forRoot({
name: '__mydb',
driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
})
],
//...
})
export class AppModule { }
The 2.x version of this plugin hard coded in the localForage-cordovaSQLiteDriver. This driver has been removed from the core code as of 3.x to provide more options for SQLite storage engines.
In 3.x there are at least two good options for SQLite usage:
-
For non-enterprise apps, the old
localForage-cordovaSQLiteDriver
is still a fine choice but does not support encryption and is community maintained. See below for installation instructions. -
For enterprise apps, we strongly recommend Ionic Secure Storage which is an enterprise SQLite engine with full encryption support out of the box and is fully supported and maintained by the Ionic team.
# If using Cordova, install the plugin using
ionic cordova plugin add cordova-sqlite-storage
# If using Capacitor, install the plugin using
npm install cordova-sqlite-storage
# Then, install the npm library
npm install localforage-cordovasqlitedriver
For non-Angular projects, pass the CordovaSQLiteDriver._driver
to the driverOrder
config option:
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
const store = new Storage({
driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
});
In Angular, pass the same configuration when importing the IonicStorageModule
in your page or app NgModule
:
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
@NgModule({
imports: [
// ...,
IonicStorageModule.forRoot({
driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB]
})
],
// ...
})
export class MyPageModule { }
Finally, to register the driver, run defineDriver()
on the storage instance to register the driver, making sure to call this before any data operations:
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver'
await this.storage.defineDriver(CordovaSQLiteDriver);
Ionic Secure Storage is an enterprise-ready, high-performance data store with SQL or key/value support and offering 256-bit AES encryption. When used in tandem with Ionic Identity Vault, developers can securely manage encryption keys and build fully offline-enabled apps with biometric authentication using the fullest security capabilities available on modern mobile devices and operating systems.
Ionic Secure Storage is an enterprise product and requires an active enterprise subscription or trial. To learn more and request a demo, visit the Secure Storage product page.
Follow the official installation guide to set up and install @ionic-enterprise/secure-storage
.
import { Drivers } from '@ionic/storage';
import IonicSecureStorageDriver from '@ionic-enterprise/secure-storage/driver';
const store = new Storage({
driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
});
await store.defineDriver(IonicSecureStorageDriver);
Usage in Angular using Services and Dependency Injection requires importing the IonicStorageModule
and then injecting the Storage
class.
First, edit your NgModule declaration in src/app/app.module.ts
or in the module for the page you'll use the storage library in, and add IonicStorageModule
as an import:
import { Drivers } from '@ionic/storage';
import { IonicStorageModule } from '@ionic/storage-angular';
@NgModule({
declarations: [
...
],
imports: [
IonicStorageModule.forRoot({
driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
})
],
// ...
})
export class AppModule { }
Then register the driver in your component:
async ngOnInit() {
await this.storage.defineDriver(IonicSecureStorageDriver);
await this.storage.create();
}
Then follow the instructions below to configure encryption support:
3.x adds a new method setEncryptionKey
to support encryption when using with Ionic Secure Storage (see instructions above).
This is an enterprise feature for teams with high security needs and provides the ability to use the simple @ionic/storage
key-value API, or drop down to SQL for more powerful query and relational data support, all with full encryption. When paired with Ionic Identity Vault teams can safely manage encryption keys and provide biometric authentication when on or offline.
Visit the Secure Storage product page to learn more about Secure Storage and inquire about a trial.
A one-time migration must be performed to move to a new, encrypted database powered by Ionic Secure Storage.
First, follow the installation steps above to update to Ionic Storage v3, install the localForage-CordovaSQLiteDriver
SQLite driver, and integrate Ionic Secure Storage.
Next, remove the database name and drivers, if used, from app.module.ts
:
@NgModule({
imports: [
// ...,
IonicStorageModule.forRoot()
],
// ...
})
export class MyPageModule { }
Finally, in the service class, create a one time migration function that migrates data to an encrypted database. Execute this function on app load.
async migrateDatabase() {
const origStore = new Storage({
name: 'originalDB', // the original database name
driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
});
await origStore.defineDriver(CordovaSQLiteDriver);
const newStore = new Storage({
name: 'encryptedDB', // pick a new db name for the encrypted db
driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
});
await newStore.defineDriver(IonicSecureStorageDriver);
newStore.setEncryptionKey('mykey');
if (await origStore.length() > 0) {
// copy existing data into new, encrypted format
await origStore.forEach((key, value, index) => {
newStore.set(key, value);
});
// remove old data
await origStore.clear();
}
this._storage = newStore;
}